epiq 0.3.0 → 0.3.2

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.
package/dist/mcp.js CHANGED
@@ -1,40 +1,40 @@
1
1
  #!/usr/bin/env node
2
- import{McpServer as xs}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as Is}from"@modelcontextprotocol/sdk/server/stdio.js";import{z as S}from"zod";var m={INIT:"init",HELP:"help",NEW:"new",TAG:"tag",MOVE:"move",PEEK:"peek",FILTER:"filter",ASSIGN:"assign",DELETE:"delete",RENAME:"rename",CLOSE_ISSUE:"close",RE_OPEN_ISSUE:"reopen",SET_DESCRIPTION:"edit",SET_EDITOR:"set:editor",SET_VIEW:"set:view",SET_USERNAME:"set:username",SYNC:"sync",NONE:""},oe={None:"none",Invalid:"invalid",Valid:"valid"},Z={None:"none",Success:"success",Fail:"fail"},i=e=>({result:Z.Fail,message:e,data:null}),c=(e,t)=>({result:Z.Success,message:e,data:t}),pn=()=>({result:Z.None,message:"No result",data:null}),a=e=>e.result==="fail";import{ulid as to}from"ulid";import Me from"chalk";import{monotonicFactory as gs,ulid as de}from"ulid";import{useSyncExternalStore as Xu}from"react";var P={WORKSPACE:"WORKSPACE",BOARD:"BOARD",SWIMLANE:"SWIMLANE",TICKET:"TICKET",FIELD:"FIELD",FIELD_LIST:"FIELD_LIST",TEXT:"TEXT"};function J(e){return e.context==="TICKET"}var p={DEFAULT:"default",MOVE:"move",HELP:"help",COMMAND_LINE:"command-line"};function ze(e,t){let n=Math.min(e.length,t.length),r=0;for(;r<n&&e[r]===t[r];)r++;return r}var qe=e=>typeof e!="string"?"":e.replace(/[\x00-\x08\x0B-\x1F\x7F]/g,"").replace(/[\r\n\t]/g," ").replace(/\s+/g," ").trim();var gn=e=>{let t=new Map;for(let n of e)for(let r=1;r<=n.length;r++){let o=n.slice(0,r),s=t.get(o);s?s.push(n):t.set(o,[n])}return t},fn=(e,t)=>t?e.get(t)??[]:[];var vn=new WeakMap,mo=e=>{let t=vn.get(e);return t||(t=gn(e),vn.set(e,t)),t};var yn=({wordList:e,inputToMatch:t,overlapThreshold:n=1})=>{let r=t.toLowerCase();return fn(mo(e),r).filter(s=>ze(r,s)>=n)};var En=({inputToMatch:e,lastWord:t},n)=>{if(t.endsWith(" "))return{hint:"",hints:[],overlap:0,remainder:""};let r=yn({wordList:n,inputToMatch:e,overlapThreshold:1});return po(t,r)},po=(e,t)=>{let n=t[0]??"",r=ze(e.toLowerCase(),n.toLowerCase()),o=n?n+" ":"",s=o.slice(r);return{hint:o,hints:t,overlap:r,remainder:s}};var Nn=["vi","vim","nvim","nano","micro","emacs","hx","code","code-insiders","subl","notepad","notepad++","idea","webstorm","default","system","$EDITOR","$VISUAL"];var Ie=24n,go=Ie*4n,Ge=(1n<<go)-1n,fo=/^[0-9a-f]+$/;function xn(e){if(!e||!fo.test(e))throw new Error(`Invalid hex rank: ${e}`);return BigInt("0x"+e)}function Je(e,t=Ie){if(e<0n)throw new Error("Negative rank not allowed");return e.toString(16).padStart(Number(t),"0")}function De(e,t){if(!e&&!t)return Je(Ge/2n,Ie);let n=e?xn(e):0n,r=t?xn(t):Ge;if(r<=n)return Je(Ge/2n,Ie);let o=(n+r)/2n;return o===n||o===r?"":Je(o,Ie)}function Y(){return Je(Ge/2n,Ie)}var ee={workspace:(e,t)=>({id:e,title:t,rank:Y(),isDeleted:!1,props:{},context:P.WORKSPACE,childRenderAxis:"vertical",parentNodeId:null,readonly:!0,log:[]}),board:(e,t,n,r=!1)=>({id:e,title:t,rank:Y(),isDeleted:!1,props:{},context:P.BOARD,childRenderAxis:"horizontal",parentNodeId:n,readonly:r,log:[]}),swimlane:(e,t,n)=>({id:e,title:t,rank:Y(),isDeleted:!1,props:{},context:P.SWIMLANE,childRenderAxis:"vertical",childNavigationAcrossParents:!0,parentNodeId:n,readonly:!1,log:[]}),field:(e,t,n,r={},o="horizontal")=>({id:e,title:t,rank:Y(),isDeleted:!1,props:r,context:P.FIELD,childRenderAxis:o,parentNodeId:n,readonly:!1,log:[]}),ticket:(e,t,n)=>({id:e,title:t,rank:Y(),isDeleted:!1,props:{},context:P.TICKET,childRenderAxis:"vertical",parentNodeId:n,readonly:!1,log:[]}),text:({id:e,name:t,parentNodeId:n,props:r={},readonly:o=!0})=>({id:e,title:t,rank:Y(),isDeleted:!1,props:r,context:P.TEXT,childRenderAxis:"vertical",parentNodeId:n,readonly:o,log:[]})};var V=e=>Object.values(y().nodes).filter(t=>!!t&&!t.isDeleted&&t.parentNodeId===e).sort((t,n)=>t.rank.localeCompare(n.rank)),In=(e,t)=>e.findIndex(n=>n.id===t),Lt=(e,t={at:"end"})=>{if(e.length===0)return c("Resolved rank",Y());switch(t.at){case"start":{let n=e[0];return n?c("Resolved rank",De(void 0,n.rank)):i("Unable to resolve first sibling")}case"end":{let n=e[e.length-1];return n?c("Resolved rank",De(n.rank,void 0)):i("Unable to resolve last sibling")}case"before":{let n=In(e,t.sibling);if(n<0)return i("Sibling not found");let r=n>0?e[n-1]:void 0,o=e[n];return o?c("Resolved rank",De(r?.rank,o.rank)):i("Sibling not found")}case"after":{let n=In(e,t.sibling);if(n<0)return i("Sibling not found");let r=e[n],o=n<e.length-1?e[n+1]:void 0;return r?c("Resolved rank",De(r.rank,o?.rank)):i("Sibling not found")}}};var Ye=(e,t)=>{let{nodes:n}=y(),r=n[e];if(!r)return i("Node not found");if(r.context===t)return c("Resolved ancestor node",r);let o=r.parentNodeId?n[r.parentNodeId]:void 0;for(;o;){if(o.context===t)return c("Resolved ancestor node",o);o=o.parentNodeId?n[o.parentNodeId]:void 0}return i(`No ancestor found for context: ${t}`)},vo=(e,t)=>{let{nodes:n}=y(),r=n[e];for(;r?.parentNodeId;){if(r.parentNodeId===t)return!0;r=n[r.parentNodeId]}return!1},Pt=(e,t)=>e?e.readonly?i({move:"Cannot move readonly node",rename:"Cannot rename readonly node",edit:"Cannot edit readonly node"}[t]):null:i("Node not found"),N={deleteNode(e){j(t=>{let n={...t.nodes};return delete n[e],{...t,nodes:n}})},editValue(e,t){let{nodes:n}=y(),r=n[e];if(!r)return i("Edit target node not found");let o=Pt(r,"edit");if(o)return o;let s={...r,props:{...r.props,value:t}};return N.updateNode(s),c("Issue description updated",{md:t})},renameNode(e,t){let n=this.getNode(e);if(!n)return i("Rename target node not found");let r=Pt(n,"rename");if(r)return r;let o={...n,title:t};return this.updateNode(o),c("Renamed node",o)},getExistingTags(){let{tags:e}=y();return[...new Set(Object.values(e).map(t=>t.name).filter(Boolean))]},getExistingAssignees(){let{contributors:e}=y();return[...new Set(Object.values(e).map(t=>t.name).filter(Boolean))]},getFieldByTitle(e,t){return V(e).find(n=>n.title===t)},moveNode({id:e,parentId:t,position:n={at:"end"}}){let{rootNodeId:r}=y(),o=this.getNode(e),s=this.getNode(t);if(!o)return i("Node not found");if(!s)return i("Target parent not found");if(r===e)return i("Cannot move root node");if(e===t)return i("Cannot move node into itself");let d=Pt(o,"move");if(d)return d;if(vo(t,e))return i("Cannot move node into its own descendant");let l=V(t).filter(v=>v.id!==e),u=Lt(l,n);if(a(u))return u;let f={...o,parentNodeId:t,rank:u.data};return this.updateNode(f),c("Moved node successfully",f)},tombstoneNode(e){let{nodes:t,currentNodeId:n,rootNodeId:r}=y(),o=this.getNode(e);if(!o)return i("Node not found");if(r===e)return i("Cannot delete root node");let s=new Set,d=u=>{let f=t[u];if(!(!f||s.has(u))){s.add(u);for(let v of V(f.id))d(v.id)}};d(e);let l={...structuredClone(t)};for(let u of s){if(!l[u])return i("Unable to locate node to delete");l[u]={...l[u],isDeleted:!0}}return n?(I({nodes:l}),c("Successfully tomb stoned",o)):i("Unable to delete undefined")},createContributor(e){let t=j(n=>({...n,contributors:{...n.contributors,[e.id]:e}}));return a(t)?i("Unable to create contributor"):c("Created contributor",e)},assign(e,t,n){let r=N.getContributor(t),o=N.getNode(e);if(!o||!r)return i("Unable assign contributor to issue");let s=this.getFieldByTitle(o.id,"Assignees");if(!s)return i("Unable to locate assignees field");if(V(s.id).some(u=>u.props?.value===t))return i("Contributor already assigned");let l=this.createNodeAtPosition(ee.field(n,r.name,s.id,{value:t}));return a(l)?l:c("Assigned contributor",l.data)},createTag(e){let t=j(n=>({...n,tags:{...n.tags,[e.id]:e}}));return a(t)?i("Could not create tag"):c("Tag created",e)},tag(e,t,n){let r=N.getTag(t),o=N.getNode(e);if(!r)return i("Unable to add tag, missing tag");if(!o)return i("Unable to add tag, missing target");let s=this.getFieldByTitle(o.id,"Tags");if(!s)return i("Unable to locate tags field");if(V(s.id).some(u=>u.props?.value===t))return i("Tag already assigned");let l=this.createNodeAtPosition(ee.field(n,r.name,s.id,{value:t}));return a(l)?l:c("Tag added",l.data)},createNodeAtPosition(e,t={at:"end"}){if(!e.parentNodeId){let s={...e,rank:Y()};return this.createNode(s),c("Created node",s)}let n=V(e.parentNodeId),r=Lt(n,t);if(a(r))return r;let o={...e,rank:r.data};return this.createNode(o),c("Created node",o)},createNode(e){let t=j(n=>({...n,nodes:{...n.nodes,[e.id]:e}}));return a(t)?i("Unable to create node"):c("Node created",e)},lockNode(e){let t=this.getNode(e);if(!t)return i("Failed to locate node");let n={...t,readonly:!0},r=j(o=>({...o,nodes:{...o.nodes,[e]:n}}));return a(r)?i(r.message):c("Locked node",n)},updateNode(e){let t=j(n=>({...n,nodes:{...n.nodes,[e.id]:e}}));return a(t)?t:c("Updated node",e)},getContributor(e){return y().contributors[e]},getTag(e){return y().tags[e]},getNode(e){return y().nodes[e]},getSiblings:e=>Object.values(y().nodes).filter(t=>!t.isDeleted&&t.parentNodeId===e).sort((t,n)=>t.rank.localeCompare(n.rank))};var Xe={preferredEditor:null,userName:null,userId:null},ie=()=>Xe,Dt=e=>(Xe={...Xe,...e},Xe);var Cn=()=>{let e=ie(),t=!!e.userName?.trim(),n=!!e.preferredEditor?.trim();return{isSetup:n&&t,hasPreferredEditor:n,hasUserName:t,userName:e.userName,preferredEditor:e.preferredEditor}},bn=()=>!Fe();var W={bg:"#1a1b26",fg:"#c8d3ff",grayDark:"#2a2f45",gray:"#46507a",grayLight:"#969bb5",cyan:"#88d5ee",cyanSoft:"#8fe6fb",blue:"#5b8cff",magenta:"#a78bfa",magentaSoft:"#c4b5fd",green:"#8fdc8c",yellow:"#f1c27d",red:"#ff7a90",white:"#ffffff"},hn={accent:W.cyan,accent2:W.magenta,primary:W.white,secondary:W.grayDark,secondary2:W.grayLight,gray:W.gray,green:W.green,yellow:W.yellow,red:W.red};var g={red:W.red,yellow:W.yellow,green:W.green,blue:W.blue,magenta:W.magenta,cyan:W.cyan},Qe={urgent:g.red,critical:g.red,important:g.red,blocker:g.red,asap:g.red,immediate:g.red,fail:g.red,failure:g.red,broken:g.red,bug:g.red,error:g.red,incident:g.red,outage:g.red,production:g.red,crash:g.red,security:g.red,warning:g.yellow,warn:g.yellow,risky:g.yellow,risk:g.yellow,attention:g.yellow,pending:g.yellow,review:g.yellow,"needs-review":g.yellow,qa:g.yellow,testing:g.yellow,test:g.yellow,validate:g.yellow,verification:g.yellow,staging:g.yellow,check:g.yellow,"follow-up":g.yellow,followup:g.yellow,waiting:g.yellow,blocked:g.yellow,hold:g.yellow,done:g.green,complete:g.green,completed:g.green,success:g.green,ok:g.green,stable:g.green,resolved:g.green,fixed:g.green,closed:g.green,merged:g.green,released:g.green,deployed:g.green,approved:g.green,verified:g.green,working:g.green,healthy:g.green,pass:g.green,passing:g.green,info:g.blue,information:g.blue,note:g.blue,docs:g.blue,documentation:g.blue,doc:g.blue,guide:g.blue,help:g.blue,explanation:g.blue,detail:g.blue,details:g.blue,context:g.blue,design:g.blue,discussion:g.blue,proposal:g.blue,idea:g.blue,feature:g.magenta,enhancement:g.magenta,improvement:g.magenta,refactor:g.magenta,refactoring:g.magenta,cleanup:g.magenta,optimize:g.magenta,optimization:g.magenta,perf:g.magenta,performance:g.magenta,upgrade:g.magenta,migration:g.magenta,modernize:g.magenta,debt:g.magenta,todo:g.cyan,next:g.cyan,planned:g.cyan,plan:g.cyan,future:g.cyan,backlog:g.cyan,investigate:g.cyan,explore:g.cyan,prototype:g.cyan};var yo=/^(\d+)(h|d|w|mo|y)$/,Eo=/^(\d{4})-(\d{2})-(\d{2})(?:(?::|\s)(\d{2}):(\d{2}))?$/,No=({year:e,month:t,day:n,hour:r=0,minute:o=0})=>{let s=new Date(e,t-1,n,r,o);return s.getFullYear()===e&&s.getMonth()===t-1&&s.getDate()===n&&s.getHours()===r&&s.getMinutes()===o},xo=(e,t=new Date)=>{let n=e.match(yo);if(!n)return null;let[,r,o]=n,s=Number(r);if(!Number.isInteger(s)||s<=0)return null;let d=new Date(t);switch(o){case"h":return d.setHours(d.getHours()-s),d;case"d":return d.setDate(d.getDate()-s),d;case"w":return d.setDate(d.getDate()-s*7),d;case"mo":return d.setMonth(d.getMonth()-s),d;case"y":return d.setFullYear(d.getFullYear()-s),d;default:return null}},Io=e=>{let t=e.match(Eo);if(!t)return null;let[,n,r,o,s,d]=t,l=Number(n),u=Number(r),f=Number(o),v=s?Number(s):0,E=d?Number(d):0;return No({year:l,month:u,day:f,hour:v,minute:E})?new Date(l,u-1,f,v,E):null},Ze=e=>{let t=e.trim().toLowerCase();return xo(t)??Io(t)},Rn=({date:e,horizonDate:t})=>t?e.getTime()>=t.getTime():!0,Co=[{unit:"h",from:1,to:24},{unit:"d",from:1,to:7},{unit:"w",from:1,to:52},{unit:"mo",from:1,to:12},{unit:"y",from:1,to:5}],Sn=(e=Co)=>{let t=[];for(let{unit:n,from:r,to:o}of e)for(let s=r;s<=o;s++)t.push(`${s}${n}`);return t};var bo=["BOARD","TICKET","SWIMLANE"],_=e=>{let{currentNode:t,readOnly:n,selectedNode:r}=y(),o=Cn().isSetup,s=t.context,d=r?.context,l=[m.SYNC,m.HELP,m.SET_VIEW,m.SET_EDITOR,m.SET_USERNAME],u=[m.NEW,m.RENAME,m.DELETE],f=[m.TAG,m.ASSIGN,m.CLOSE_ISSUE,m.RE_OPEN_ISSUE,m.SET_DESCRIPTION],v=[m.FILTER,m.PEEK],E={WORKSPACE:[...l,...u],BOARD:[...v,...l,...u],SWIMLANE:[...v,...l,...u],TICKET:[...l,...u,...f],FIELD:[...l,...f],FIELD_LIST:[...l,...f],TEXT:[...l]},C=d&&bo.includes(d),R=[...E[s||"WORKSPACE"]].filter(Q=>[m.RENAME,m.DELETE,m.MOVE].includes(Q)?C:!0),M={[m.PEEK]:[...Sn(),"now","prev","next"],[m.SYNC]:[],[m.INIT]:[],[m.SET_USERNAME]:[],[m.SET_DESCRIPTION]:["confirm"],[m.DELETE]:["confirm"],[m.RE_OPEN_ISSUE]:["confirm"],[m.MOVE]:["start","confirm","next","previous","to-next","to-previous","cancel"],[m.CLOSE_ISSUE]:["confirm"],[m.FILTER]:["tag","assignee","description","title","clear"],[m.SET_VIEW]:["dense","wide"],[m.SET_EDITOR]:[...Nn,"vim"],[m.TAG]:[...new Set([...Object.keys(Qe),...N.getExistingTags()])],[m.ASSIGN]:N.getExistingAssignees(),[m.HELP]:[],[m.RENAME]:[],[m.NEW]:s==="TICKET"||s==="FIELD"||s==="FIELD_LIST"?["issue","swimlane","board"]:s==="SWIMLANE"?["issue","swimlane","board"]:s==="BOARD"?["issue","swimlane","board"]:["board"],[m.NONE]:R};return o?bn()?n&&(M={[m.NONE]:[m.HELP,m.PEEK],[m.HELP]:M[m.HELP],[m.PEEK]:M[m.PEEK]}):M={[m.NONE]:[m.HELP,m.INIT],[m.HELP]:M[m.HELP],[m.INIT]:M[m.INIT]}:M={[m.NONE]:[m.HELP,m.SET_EDITOR,m.SET_USERNAME],[m.HELP]:M[m.HELP],[m.SET_EDITOR]:M[m.SET_EDITOR],[m.SET_USERNAME]:M[m.SET_USERNAME]},M[e]??[]};import tt from"chalk";import{decodeTime as An}from"ulid";var wn=e=>{try{return c("Decoded date",new Date(An(e)))}catch(t){return i("Decoding failed + "+t.message)}},Ft=e=>{if(!e?.id)return null;try{return An(e.id)}catch{return null}};var ve=(e,t)=>{let n=e.find(r=>r.context===t);return n!==void 0?c("Found node",n):i("Unable to find node in breadcrumb")};import Tn from"chalk";var Ot={stringColor:{saturation:50,lightness:60},gradient:{stops:[[174,150,240],[92,138,232],[102,204,226]]}},ho=(e,t,n)=>Math.max(t,Math.min(n,e)),kt=(e,t,n)=>e+(t-e)*n,Mn=e=>{let t=0;for(let n=0;n<e.length;n++)t=t*31+e.charCodeAt(n)>>>0;return t},Ro=(e,t,n)=>{let r=t/100,o=n/100,s=(1-Math.abs(2*o-1))*r,d=e/60,l=s*(1-Math.abs(d%2-1)),u=0,f=0,v=0;d>=0&&d<1?(u=s,f=l):d>=1&&d<2?(u=l,f=s):d>=2&&d<3?(f=s,v=l):d>=3&&d<4?(f=l,v=s):d>=4&&d<5?(u=l,v=s):(u=s,v=l);let E=o-s/2;return[Math.round((u+E)*255),Math.round((f+E)*255),Math.round((v+E)*255)]},So=([e,t,n])=>`#${e.toString(16).padStart(2,"0")}${t.toString(16).padStart(2,"0")}${n.toString(16).padStart(2,"0")}`,Ao=(e,t,n)=>[Math.round(kt(e[0],t[0],n)),Math.round(kt(e[1],t[1],n)),Math.round(kt(e[2],t[2],n))],wo=e=>{let n=Mn(e)%360,r=Ro(n,Ot.stringColor.saturation,Ot.stringColor.lightness);return So(r)},To=e=>{let t=Ot.gradient.stops,n=ho(e,0,1);if(t.length===0)return[0,0,0];if(t.length===1)return t[0];let r=t.length-1,o=n*r,s=Math.min(Math.floor(o),r-1),d=o-s;return Ao(t[s],t[s+1],d)},et=e=>Mn(e.toLowerCase().trim())/4294967295,Mo=e=>{let t=et(e);return To(t)},Lo=e=>{let[t,n,r]=Mo(e);return{normal:o=>Tn.bgRgb(t,n,r).black(o),cursor:o=>Tn.bgRgb(t,n,r).white.bold(o)}};var Ut=e=>Lo(e).normal(` ${e} `),_t=(e,t=Qe)=>{let r=(o=>o.toLowerCase().trim())(e);return r&&t[r]?t[r]:wo(r)};var Po=["BOARD","TICKET","SWIMLANE"],Wt=()=>{let e=y().selectedNode;return e?.context?Po.includes(e?.context)?k():U({message:"Command not available in this context",completionWordList:[]}):U({message:"Missing target context",completionWordList:[]})},z="<ENTER> to confirm",k=(e="",t=[])=>({message:e,validity:oe.Valid,completionWordList:t}),U=({message:e,completionWordList:t})=>({validity:oe.Invalid,message:e,completionWordList:t}),ke=e=>e.length===0,me=({prefix:e="",wordList:t,postfix:n="",noOfHints:r=100,inputString:o,minLengthForHints:s=1})=>{let u=[...t.filter(Boolean).filter(v=>v.startsWith(o.trim()))].sort((v,E)=>et(v)-et(E)).slice(0,r).map(Ut),f=u.length>s?u.join(" "):"";return f?`${e}${f}${n}`:""},Bt=({modifier:e})=>{let t="confirm";return e===t?k(z):U({message:ke(e)?`if you are certain, enter ${Ut(t)}`:"",completionWordList:[t]})},Do=({list:e,hint:t})=>({modifier:n})=>e.includes(n)?k(z):U({message:ke(n)?t:"",completionWordList:[]}),Fo=({list:e,hint:t,onValue:n})=>({modifier:r,inputString:o})=>e.includes(r)?o.trim().length<1?U({message:n,completionWordList:[]}):k():U({message:ke(r)?t:"",completionWordList:[]}),$t=({hint:e})=>({modifier:t,inputString:n})=>ke(t)&&ke(n)?U({message:e,completionWordList:[]}):k(z),ko={[m.PEEK]:e=>{let t=e.modifier;if(t==="now")return k(z);let n={message:"historical state from: '1h', '2d', '23h', '1mo', '2y', 'previous', 'next' or full date as YYYY-MM-DD",completionWordList:[]};if(t==="prev"||t==="next")return k(z);let r=Ze(t);if(!t||!r)return U(n);let o=ve(y().breadCrumb,"BOARD");if(a(o))return U({message:"Command is not applicable in this context",completionWordList:[]});let s=wn(o.data.id);return a(s)?U({message:"Unable to peek: board id is not a valid ULID",completionWordList:[]}):Rn({date:r,horizonDate:s.data})?k(z):U({message:tt.red(`nothing to peek before ${s.data.toISOString().slice(0,16).replace("T"," ")}`),completionWordList:[]})},[m.INIT]:()=>k(z),[m.FILTER]:e=>{if(e.modifier==="clear")return k();let t=d=>_(m.FILTER).includes(d);if(!e.modifier||!t(e.modifier??""))return U({message:me({wordList:_(m.FILTER),inputString:e.inputString}),completionWordList:_(m.FILTER)});let r=Object.values(y().tags).map(d=>d.name),o=Object.values(y().contributors).map(d=>d.name),s=e.modifier==="tag"?r:e.modifier==="assignee"?o:[];return e.inputString?s.length&&!s.includes(e.inputString.trim()??"")?U({message:me({prefix:`existing ${e.modifier}s... `,wordList:s,noOfHints:10,inputString:e.inputString}),completionWordList:s}):k():U({message:me({prefix:"one of... ",wordList:s,noOfHints:10,inputString:e.inputString}),completionWordList:s})},[m.NONE]:e=>e.command?k():U({message:me({prefix:"commands... ",wordList:_(m.NONE),inputString:e.inputString,minLengthForHints:0}),completionWordList:[]}),[m.NEW]:e=>Fo({list:_(m.NEW),hint:me({wordList:_(m.NEW),noOfHints:3,inputString:e.inputString,minLengthForHints:0}),onValue:"provide a name..."})(e),[m.SET_DESCRIPTION]:()=>k(z),[m.HELP]:()=>k(z),[m.RENAME]:()=>{let e=Wt();return e.validity==="invalid"?e:k(z)},[m.DELETE]:e=>{let t=Wt();return t.validity==="invalid"?t:Bt(e)},[m.CLOSE_ISSUE]:e=>Bt(e),[m.RE_OPEN_ISSUE]:e=>Bt(e),[m.MOVE]:e=>{let t=Wt();return t.validity==="invalid"?t:$t({hint:me({prefix:"hey hacker! These commands are blocked for you... ",wordList:_(m.MOVE),noOfHints:10,inputString:e.inputString})})(e)},[m.TAG]:e=>{let t=N.getExistingTags().map(n=>` ${tt.bgHex(_t(n))(" "+n+" ")} `).slice(0,10);return $t({hint:"tag name like... "+t.join("")})(e)},[m.ASSIGN]:e=>{let t=N.getExistingAssignees().map(n=>` ${tt.bgHex(_t(n))(" "+n+" ")} `).slice(0,10);return $t({hint:"assign to... "+t.join("")})(e)},[m.SET_EDITOR]:e=>{logger.debug(`Validating command: ${e.command} ${e.modifier} ${e.inputString}`);let t=_(m.SET_EDITOR);return e.modifier?k(z):U({message:me({wordList:t,inputString:e.inputString}),completionWordList:[]})},[m.SET_USERNAME]:e=>e.inputString?k():U({message:`Enter a username. Saved in ${tt.bgBlack("~/.epiq/")}`,completionWordList:[]}),[m.SET_VIEW]:e=>Do({list:_(m.SET_VIEW),hint:me({wordList:_(m.SET_VIEW),noOfHints:3,inputString:e.inputString})})(e),[m.SYNC]:()=>k(z)},Ln=Object.fromEntries(Object.entries(ko).map(([e,t])=>[e,{validate:(n,r,o)=>t({modifier:r,command:n,inputString:o})}]));var Pn=["frontend","backend","infrastructure","architecture","integration","configuration","implementation","application","deployment","environment","framework","platform","service","component","module","gateway","pipeline","containerization","orchestrator","exception","incident","defect","regression","degradation","malfunction","instability","intermittent","reproducibility","reproduction","investigation","triage","workaround","mitigation","remediation","optimization","stabilization","refinement","failure","outage","blocking","criticality","severity","escalation","diagnostics","analysis","resolution","corruption","inconsistency","validation","verification","authorization","authentication","confidentiality","availability","accessibility","reliability","compliance","governance","encryption","decryption","integrity","auditing","traceability","accountability","protection","privileges","permissions","dependency","orchestration","provisioning","synchronization","compatibility","incompatibility","interoperability","observability","instrumentation","telemetry","loadbalancing","discovery","registration","scheduling","coordination","distribution","isolation","virtualization","serialization","deserialization","initialization","instantiation","propagation","aggregation","consolidation","normalization","standardization","transformation","reconciliation","correlation","processing","indexing","partitioning","enrichment","validation","filtering","streaming","batching","concurrency","parallelism","contention","deadlock","throttling","ratelimiting","backpressure","fragmentation","saturation","exhaustion","partitioning","replication","redundancy","failover","deprecation","obsolescence","starvation","overload","underutilization","latency","throughput","refactoring","modularization","encapsulation","abstraction","extensibility","configurability","maintainability","recoverability","sustainability","readability","testability","debuggability","reusability","simplicity","consistency","performance","functionality","requirement","recommendation","improvement","enhancement","clarification","documentation","description","acceptance","criteria","estimation","prioritization","dependency","deliverable","milestone","iteration"];var b={Init:"init",None:"none",ViewHelp:"view-help",Rename:"rename",Edit:"edit",Delete:"delete",Filter:"filter",Move:"move",Peek:"peek",SetView:"set-view",SetEditor:"set-editor",SetUserName:"set-user-name",NewItem:"add-new-item",TagTicket:"ticket-tag",AssignUserToTicket:"ticket-assign-user",CloseIssue:"close-issue",ReopenIssue:"re-open-issue",Sync:"sync"};var Dn=e=>Object.values(m).includes(e),Fn=(e,t)=>{let n=e.command??"",{modifier:r,target:o,inputString:s}=e,{message:d,validity:l,completionWordList:u}=Ln[n].validate(n,r,s),f=o==="command"?Object.values(m):n&&e.target==="modifier"?_(n):Pn;return{validity:l,command:e.command,modifier:e.modifier,inputString:e.inputString,infoMessage:d??"",autoCompletion:t?En(e,[...u,...f]):{hint:"",hints:[],remainder:"",overlap:0}}};var kn=e=>{let t=e.trimStart(),n=Uo(t),r=(n[0]??"").trimStart().trimEnd(),o=(n[1]??"").trimStart().trimEnd(),s=_o(e),d=Dn(r)?r:null,l=d!==null,u=r!=="",f=e.endsWith(" "),v=d?_(d)??[]:[],E=d&&v.includes(o)?o:"",C="word";n.length<=1?C="command":n.length===2&&(C="modifier");let R=Oo(t,d,E);return{raw:e,trimmedStart:t,words:n,firstWord:r,lastWord:s,hasCommand:u,command:d,isCommandKeyword:l,isLastWordCompleted:f,modifier:E,target:C,inputToMatch:s,inputString:R}},Oo=(e,t,n)=>{let r=e;return t&&r.startsWith(t)&&(r=r.slice(t.length)),r=r.replace(/^\s+/,""),n&&r.startsWith(n)&&(r=r.slice(n.length),r=r.replace(/^\s+/,"")),r},Uo=e=>e?e.split(/\s+/):[],_o=e=>e.trimEnd().split(/\s+/).at(-1)??"";var On=" ",Ce={commandHistory:[],value:"",commandHistoryIndex:-1,cursorPosition:0,commandIsPending:!1,commandMeta:{command:null,modifier:"",infoMessage:"",inputString:"",validity:oe.None,autoCompletion:{hint:"",hints:[],remainder:"",overlap:0}}},Wo=new Set,Un=()=>{for(let e of Wo)e()};var se=e=>{let n=e(Ce),r=kn(n.value),o=n.cursorPosition===n.value.length;Ce={...n,commandMeta:Fn(r,o)},Un()},Oe=({message:e,result:t})=>{let n=structuredClone(Ce);return n.commandMeta={...n.commandMeta,infoMessage:e??"",validity:t==="fail"?"invalid":"valid"},n.commandIsPending=!0,Ce=n,Un(),c(e,null)},Ht=e=>{se(t=>({...t,cursorPosition:Math.max(0,Math.min(t.value.length,t.cursorPosition+e))}))},Kt=e=>{se(t=>{let{value:n,cursorPosition:r}=t,o=r;if(e==="left"){for(;o>0&&n[o-1]===" ";)o--;for(;o>0&&n[o-1]!==" ";)o--}else{for(;o<n.length&&n[o]!==" ";)o++;for(;o<n.length&&n[o]===" ";)o++}return{...t,cursorPosition:o}})},_n=()=>{se(e=>{let t=e.value.slice(e.cursorPosition),n=Math.max(0,e.cursorPosition-1);return{...e,value:e.value.slice(0,n)+t,cursorPosition:n,commandIsPending:!1}})},Wn=()=>{se(e=>{let{value:t,cursorPosition:n}=e,r=n;for(;r>0&&t[r-1]===" ";)r--;for(;r>0&&t[r-1]!==" ";)r--;let o=t.slice(n);return{...e,value:t.slice(0,r)+o,cursorPosition:r,commandIsPending:!1}})},D=e=>{se(t=>{let n=Math.max(0,Math.min(t.cursorPosition,t.value.length)),r=t.value.slice(0,n),o=t.value.slice(n),s=e(r,t.commandMeta.autoCompletion),d=s+o,l=Math.max(0,Math.min(s.length,d.length));return{...t,value:d,cursorPosition:l,commandIsPending:!1}})},Bn=()=>{se(e=>({...e,commandIsPending:!0}))},$n=({addToHistory:e=!0})=>{se(n=>({...n,commandHistory:e?[n.value,...n.commandHistory].slice(0,40):n.commandHistory,commandHistoryIndex:-1,commandIsPending:!1})),Bo()},Hn=()=>{se(e=>{let t=Math.min(e.commandHistoryIndex+1,e.commandHistory.length-1),n=e.commandHistory[t]??"";return{...e,commandHistoryIndex:t,value:n,cursorPosition:n.length}})},Kn=()=>{se(e=>{let t=Math.max(e.commandHistoryIndex-1,-1),n=t===-1?"":e.commandHistory[t]??"";return{...e,commandHistoryIndex:t,value:n,cursorPosition:n.length}})},Bo=()=>D(()=>""),te=()=>Ce,nt=()=>{let[e,...t]=Ce.value.split(On);return t.join(On).trim()};var h={Sync:"sync",NavPreviousItem:"navPreviousItem",NavNextItem:"navNextItem",NavToPreviousContainer:"navToPreviousContainer",NavToNextContainer:"navToNextContainer",MovePreviousItem:"movePreviousItem",MoveNextItem:"moveNextItem",MoveToPreviousContainer:"moveToPreviousContainer",MoveToNextContainer:"moveToNextContainer",Confirm:"confirm",Exit:"exit",ViewHelp:"viewHelp",HideHelp:"hideHelp",InitMove:"initMove",ConfirmMove:"confirmMove",Delete:"Delete",InitCommandLine:"initCommandLine",ExitCommandLine:"exitCommandLine",CaptureInput:"captureInput",EraseInput:"eraseInput",AddItem:"addItem",GetLastCommandFromHistory:"getLastCommandFromHistory",GetNextCommandFromHistory:"getNextCommandFromHistory",AutoCompleteCommand:"autoCompleteCommand",MoveCursorLeft:"MoveCursorLeft",MoveCursorRight:"MoveCursorRight",MoveCursorLeftOfWord:"MoveCursorLeftOfWord",MoveCursorRightOfWord:"MoveCursorRightOfWord",EraseInputWord:"EraseInputWord",None:"None",Edit:"edit",SetViewDense:"SetViewDense",SetViewWide:"SetViewWide"};var Vn=e=>{let{context:t}=y()?.currentNode;if(!t)return b.None;switch(e){case m.INIT:return b.Init;case m.DELETE:return b.Delete;case m.SET_DESCRIPTION:return b.Edit;case m.HELP:return b.ViewHelp;case m.RE_OPEN_ISSUE:return b.ReopenIssue;case m.CLOSE_ISSUE:return b.CloseIssue;case m.TAG:return b.TagTicket;case m.ASSIGN:return b.AssignUserToTicket;case m.RENAME:return b.Rename;case m.NEW:return b.NewItem;case m.FILTER:return b.Filter;case m.MOVE:return b.Move;case m.PEEK:return b.Peek;case m.SET_USERNAME:return b.SetUserName;case m.SET_EDITOR:return b.SetEditor;case m.SET_VIEW:return b.SetView;case m.SYNC:return b.Sync;default:return b.None}};import{ulid as F}from"ulid";import{spawnSync as Go}from"node:child_process";import Jo from"node:os";import Gn from"node:path";import{ulid as Yo}from"ulid";import{accessSync as $o,copyFileSync as Ho,existsSync as rt,mkdirSync as jn,readdirSync as zn,readFileSync as Ko,renameSync as Vo,rmSync as jo,statSync as qn,unlinkSync as zo,writeFileSync as qo}from"node:fs";import be from"node:path";var q={writeToFile:(e,t)=>{try{let n=be.dirname(e);rt(n)||jn(n,{recursive:!0});let r=typeof t=="string"?t:JSON.stringify(t,null,2);qo(e,r,"utf-8")}catch(n){logger.error(`Failed to write file at ${e}:`,n)}},readFile:e=>{try{return Ko(e,"utf-8")}catch(t){return logger.error(`Failed to read file at ${e}:`,t),null}},readFileJSON(e){try{let t=q.readFile(e);return t===null?null:JSON.parse(t)}catch(t){return logger.error(`Failed to read JSON at ${e}:`,t),null}},dirExists:e=>{try{return rt(e)&&qn(e).isDirectory()}catch{return!1}},async fileExists(e){try{return await $o(e),!0}catch{return!1}},mkDir:e=>jn(e,{recursive:!0}),locateFolder:e=>{let t=process.cwd(),{root:n}=be.parse(t);for(;;){let r=be.join(t,e);try{if(rt(r)&&qn(r).isDirectory())return r}catch{logger.error(`Unable to locate folder ${e}`)}if(t===n)break;t=be.dirname(t)}return null},readFirstJSON(e){try{if(!q.dirExists(e))return null;let t=zn(e).filter(r=>r.endsWith(".json")).sort()[0];if(!t)return null;let n=be.join(e,t);return q.readFileJSON(n)}catch(t){return logger.error(`Could not read first JSON in folder ${e}`,t),null}},listDir:e=>{try{return q.dirExists(e)?zn(e):[]}catch(t){return logger.error(`Failed to list dir ${e}`,t),[]}},rmFile(e){try{zo(e)}catch(t){t?.code!=="ENOENT"&&logger.error(`Unable to remove file ${e}`)}},rmDir(e){try{jo(e,{recursive:!0,force:!0})}catch(t){t?.code!=="ENOENT"&&logger.error(`Unable to remove dir ${e}`)}},moveFile(e,t,n){if(this.mkDir(be.dirname(t)),!n?.overwrite&&rt(t))throw new Error(`moveFile: destination exists: ${t}`);n?.overwrite&&this.rmFile(t);try{Vo(e,t)}catch(r){if(r?.code==="EXDEV"){Ho(e,t),this.rmFile(e);return}throw r}}};function Xo(){let{preferredEditor:e}=ie(),t=[e,process.env.VISUAL,process.env.EDITOR,"vim","vi","nano"].filter(n=>!!n?.trim());return[...new Set(t)]}function Qo(e,t){return/(^|\/)code(-insiders)?$/.test(e.trim())?`${e} --wait "${t}"`:`${e} "${t}"`}function Jn(e){let t=Gn.join(Jo.tmpdir(),"epiq");q.mkDir(t);let n=Gn.join(t,Yo());q.writeToFile(n,e??"");let r=Xo();for(let o of r){let s=Qo(o,n),d=Go(s,{stdio:"inherit",shell:!0});if(!d.error&&d.status===0){let l=q.readFile(n);if(l==null)return i("Unable to read edited file");let u=l.replace(/\r?\n$/,"");return c("Successfully edited",u)}}return i("Unable to open editor")}import{monotonicFactory as Zo,ulid as ot}from"ulid";var it=Zo(),st=({name:e,parent:t,user:{userId:n,userName:r}})=>{let o=it(),s=it(),d=it(),l=it();return[{id:ot(),userId:n,userName:r,action:"add.issue",payload:{id:o,parent:t,name:e}},{id:ot(),userId:n,userName:r,action:"add.field",payload:{id:s,parent:o,name:"Description",val:""}},{id:ot(),userId:n,userName:r,action:"add.field",payload:{id:d,parent:o,name:"Assignees"}},{id:ot(),userId:n,userName:r,action:"add.field",payload:{id:l,parent:o,name:"Tags"}}]};import ut from"node:fs";import mt from"node:path";import{z as jt}from"zod";var at=process.env.IS_LOCAL==="true",ne=()=>".epiq";import dt from"node:fs";import ye from"node:path";import{decodeTime as ei,monotonicFactory as ti}from"ulid";import{z as Ue}from"zod";var Yn=e=>({action:e.action,payload:e.payload});var Qn=1,Xn=ti(),ni="events",ri=Ue.tuple([Ue.string().min(1),Ue.string().min(1).nullable()]),oi=Ue.looseObject({v:Ue.literal(Qn),id:ri}),Vt=e=>{let t=oi.safeParse(e);return t.success?c("Parsed persisted event",t.data):i(`Invalid persisted event: ${t.error.issues.map(n=>n.path.join(".")||n.message).join(", ")}`)},ct=e=>e.trim().toLowerCase().replace(/[^a-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||"unknown",H=()=>{let{userName:e,userId:t}=ie();return e?t?e.trim()?c("Successfully resolved actor ID",{userId:ct(t),userName:ct(e)}):i("Unable to resolve actor ID from settings or OS user info"):i("User ID not configured"):i("User name not configured")},ii=e=>dt.existsSync(ye.join(e,ne()))&&dt.statSync(ye.join(e,ne())).isDirectory(),ae=(e=process.cwd())=>{let t=ye.resolve(e);for(;;){if(ii(t))return t;let n=ye.dirname(t);if(n===t)return ye.resolve(e);t=n}},Zn=(e=process.cwd())=>ye.join(ae(e),ne(),ni),_e=({userId:e,userName:t})=>`${ct(e)}.${ct(t)}.jsonl`,si=(e=process.cwd(),{userId:t,userName:n})=>{let r=_e({userId:t,userName:n});return/^(?!.*\.jsonl.*\.jsonl).*\.jsonl$/.test(r)?c("Successfully resolved event log path",ye.join(Zn(e),r)):i(`Invalid event log file name: ${r}`)},ai=(e,t)=>{let n={[e.action]:e.payload,v:Qn,id:t};return Vt(n)};function lt({event:e,rootDir:t=process.cwd()}){try{let n=ae(t),r=Zn(n),o=si(n,{userId:e.userId,userName:e.userName});if(a(o))return o;dt.mkdirSync(r,{recursive:!0});let s=er(n);if(a(s))return i(s.message);let d;if(s.data){let u=ei(s.data),f=Math.max(Date.now(),u+1);d=Xn(f)}else d=Xn();let l=ai(Yn(e),[d,s.data]);return a(l)?i(l.message):(dt.appendFileSync(o.data,`${JSON.stringify(l.data)}
3
- `,"utf8"),c("Event persisted",{path:o.data,entry:l.data}))}catch(n){let r=n instanceof Error?n.message:"Unknown persist error";return i(`Failed to persist event: ${r}`)}}import{decodeTime as di}from"ulid";var ci=ne(),li="events",ui=jt.object({userId:jt.string().min(1).default("unknown"),userName:jt.string().min(1).default("unknown")}),mi=(e=process.cwd())=>mt.join(ae(e),ci,li),pi=e=>{let[t,n]=mt.basename(e,".jsonl").split("."),r=ui.safeParse({userId:t,userName:n});return r.success?c("Parsed event file actor",r.data):i(`Invalid event file name ${mt.basename(e)}: ${r.error.issues.map(o=>o.path.join(".")||o.message).join(", ")}`)},gi=e=>{let t=Object.keys(e).filter(n=>n!=="id"&&n!=="v");return t.length!==1?i(`Invalid persisted event: expected exactly 1 action key, got ${t.length}`):!t[0]||!(t[0]in e)?i("Invalid persisted event: action key is missing or invalid"):c("Resolved persisted action",t[0])},fi=(e,t)=>t in e,vi=({id:e,action:t,payload:n,userId:r,userName:o})=>({id:e,action:t,payload:n,userId:r,userName:o}),yi=e=>{let{userId:t,userName:n,...r}=e,o=gi(r);if(a(o))return i(o.message);let s=o.data,d=e.id?.[0];return d?fi(r,s)?c("Decoded persisted event",vi({id:d,action:s,payload:r[s],userId:t,userName:n})):i(`Persisted event is missing payload for action: ${s}`):i("Persisted event is missing id")},pt=e=>{if(!ut.existsSync(e))return c("Event file missing",[]);let t=pi(e);if(a(t))return i(t.message);let n=ut.readFileSync(e,"utf8"),r=[];for(let o of n.split(`
4
- `)){let s=o.trim();if(!s)continue;let d;try{d=JSON.parse(s)}catch{return i(`Failed to parse event JSON from ${e}: ${s}`)}let l=Vt(d);if(a(l))return i(`${l.message} in ${e}: ${s}`);r.push({...l.data,userId:t.data.userId,userName:t.data.userName})}return c("Parsed persisted events file",r)};function tr(e=process.cwd()){let t=mi(e);if(!ut.existsSync(t))return i("No events found");let n=ut.readdirSync(t).filter(o=>o.endsWith(".jsonl")).map(o=>mt.join(t,o)),r=[];for(let o of n){let s=pt(o);if(a(s))return i(s.message);r.push(...s.data)}return c("All events loaded",Ei(r))}function We(e=process.cwd()){let t=tr(e);if(a(t))return i(t.message);let n=[];for(let r of t.data){let o=yi(r);if(a(o))return i(`Failed to decode event ${r.id?.[0]??"<unknown>"}: ${o.message}`);n.push(o.data)}return c("Loaded merged events",n)}function er(e=process.cwd()){let t=tr(e);return a(t)?i(t.message):c("Loaded edge reference",t.data.at(-1)?.id?.[0]??null)}var Ei=e=>{let t=new Map(e.map(l=>[l.id[0],l])),n=new Map;for(let l of e){let u=l.id[1],f=n.get(u)??[];f.push(l),n.set(u,f)}for(let l of n.values())l.sort((u,f)=>{let[v]=u.id,[E]=f.id;return v.localeCompare(E)});let r=[],o=new Set,s=l=>{let u=n.get(l)??[];for(let f of u){let[v]=f.id;o.has(v)||(o.add(v),r.push(f),s(v))}};s(null);let d=[...e].filter(l=>{let[u]=l.id;return!o.has(u)}).sort((l,u)=>{let[f,v]=l.id,[E,C]=u.id,R=v===null||t.has(v),M=C===null||t.has(C);if(R&&!M)return-1;if(!R&&M)return 1;let Q=(v??"").localeCompare(C??"");return Q!==0?Q:f.localeCompare(E)});return[...r,...d]},nr=(e,t)=>{let n=e.findIndex(r=>{try{return di(r.id)>t}catch{return!0}});return n===-1?{appliedEvents:e,unappliedEvents:[]}:{appliedEvents:e.slice(0,n),unappliedEvents:e.slice(n)}};var rr=e=>{let t=e.log??[];for(let n=t.length-1;n>=0;n--){let r=t[n];if(r&&r.action==="close.issue"&&r.payload.id===e.id)return r.payload.parent}return null};var Ni=["00KM6CZ900T7180RM46K0JAYNF","00JR3R8E00A1Z4X9FGP9DV0SM5"],[X,gt]=Ni;var w=(e,t)=>i(`${t.split(".").join(" ")+" failed, "+e.toLowerCase()}`),xi={"init.workspace":({action:e,payload:t})=>{let{id:n,name:r}=t,o=ee.workspace(n,r);zt(o);let s=N.createNodeAtPosition(o);return a(s)?w(s.message??"Failed to initialize workspace",e):c("Workspace initialized",{action:e,result:s.data})},"add.workspace":({action:e,payload:t})=>{let{id:n,name:r}=t,o=ee.workspace(n,r),s=N.createNodeAtPosition(o);return a(s)?w(s.message??"Failed to add workspace",e):c("Added workspace",{action:e,result:s.data})},"add.board":({action:e,payload:t})=>{let{id:n,name:r,parent:o}=t,s=N.createNodeAtPosition(ee.board(n,r,o));return a(s)?w(s.message??"Unable to create board",e):c("Added board",{action:e,result:s.data})},"add.swimlane":({action:e,payload:t})=>{let{id:n,name:r,parent:o}=t,s=N.createNodeAtPosition(ee.swimlane(n,r,o));return a(s)?w(s.message??"Unable to create swimlane",e):c("Added swimlane",{action:e,result:s.data})},"add.issue":({action:e,payload:t})=>{let{id:n,name:r,parent:o}=t,s=N.createNodeAtPosition(ee.ticket(n,r,o));return a(s)?w(s.message??"Unable to create issue",e):c("Added issue",{action:e,result:s.data})},"add.field":({action:e,payload:t})=>{let{id:n,name:r,parent:o,val:s}=t,d=N.createNodeAtPosition(ee.field(n,r,o,{value:s},r.includes("Description")?"vertical":"horizontal"));return a(d)?w(d.message??`Unable to create field: ${r}`,e):c("Added field",{action:e,result:d.data})},"edit.title":({action:e,payload:t})=>{let{id:n,name:r}=t;if(!N.getNode(n))return w("Unable to locate node",e);let s=N.renameNode(n,r);return a(s)?w(s.message??"Unable to edit title",e):c("Edited title",{action:e,result:s.data})},"delete.node":({action:e,payload:t})=>{let{id:n}=t,r=N.tombstoneNode(n);return a(r)?w(r.message??"Unable to delete node",e):c("Deleted node",{action:e,result:r.data})},"create.tag":({action:e,payload:t})=>{let{id:n,name:r}=t,o=N.createTag({id:n,name:r});return a(o)?w(o.message??"Unable to create tag",e):c("Tag added",{action:e,result:o.data})},"create.contributor":({action:e,payload:t})=>{let{id:n,name:r}=t,o=N.createContributor({id:n,name:r});return a(o)?w(o.message??"Unable to create contributor",e):c("Contributor created",{action:e,result:o.data})},"tag.issue":({action:e,payload:t})=>{let{id:n,target:r,tagId:o}=t,s=N.tag(r,o,n);return a(s)?w(s.message??"Unable to tag issue",e):c("Issue tagged",{action:e,result:s.data})},"assign.issue":({action:e,payload:t})=>{let{id:n,contributor:r,target:o}=t,s=N.assign(o,r,n);return a(s)?w(s.message??"Unable to assign issue",e):c("Assigned successfully",{action:e,result:s.data})},"move.node":({action:e,payload:t})=>{let{id:n,parent:r,pos:o}=t,s=N.moveNode({id:n,parentId:r,position:o});return a(s)?w(s.message??"Failed to move node",e):c("Moved node",{action:e,result:s.data})},"edit.description":({action:e,payload:t})=>{let{id:n,md:r}=t,o=N.editValue(n,r);return a(o)?w(o.message??"Unable to edit description",e):c("Set node value",{action:e,result:o.data})},"close.issue":({action:e,payload:t})=>{let{id:n}=t,r=N.getNode(n);if(!r)return w("Unable to locate issue",e);if(!J(r))return w("Can only close issues",e);let o=N.getNode(X);if(!o)return w("Unable to locate target swimlane",e);if(o.id===r.parentNodeId)return w("Cannot close closed issue",e);let d=N.moveNode({id:n,parentId:o.id});return a(d)?w(d.message??"Unable to close issue",e):c("Issue closed",{action:e,result:d.data})},"reopen.issue":({action:e,payload:t})=>{let{id:n}=t,r=N.getNode(n);if(!r)return w("Unable to locate issue",e);if(!J(r))return w("Can only reopen issues",e);let o=N.getNode(X);if(!o)return w("Unable to locate closed swimlane",e);if(!(r.parentNodeId===o.id))return w("Issue is not closed",e);let d=rr(r);if(!d)return w("Unable to resolve previous parent from issue history",e);if(d===o.id)return w("Previous parent resolves to closed swimlane",e);if(!N.getNode(d))return w("Previous parent no longer exists",e);let u=N.moveNode({id:n,parentId:d});return a(u)?w(u.message??"Unable to reopen issue",e):c("Issue reopened",{action:e,result:u.data})},"lock.node":({action:e,payload:t})=>{let{id:n}=t,r=N.lockNode(n);return a(r)?w(r.message??"Unable to lock node",e):c("Node locked",{action:e,result:r.data})}},Ii=(e,t)=>{let n=N.getNode(e);n&&N.updateNode({...n,log:[...n.log??[],t]})},Ci=e=>{switch(e.action){case"init.workspace":case"add.workspace":case"add.board":case"add.swimlane":case"add.issue":case"add.field":case"edit.title":case"lock.node":case"delete.node":case"move.node":case"close.issue":case"reopen.issue":return[e.payload.id];case"edit.description":let t=[e.payload.id],n=y().nodes[e.payload.id]?.parentNodeId;return n&&t.push(n),t;case"tag.issue":case"assign.issue":return[e.payload.id,e.payload.target];case"create.tag":case"create.contributor":default:return[]}};function he(e,t=!1){let n=xi[e.action](e);if(a(n))return n;t||([...new Set(Ci(e))].forEach(d=>Ii(d,e)),j(d=>({...d,eventLog:[...d.eventLog,e]})));let r=e.userId,o=e.userName;return!r?.length||!o?.length?w("Invalid user ID format",e.action):(N.createContributor({name:o,id:r}),n)}var Ee=e=>e.map(t=>he(t));function K(e){let t=he(e);if(t.result!==Z.Success)return t;let n=lt({event:e});return a(n)?n:t}function Re(e){return e.map(t=>K(t))}import Ke from"node:fs";import{spawn as Ri}from"node:child_process";import Gt from"node:fs";import Se from"node:path";var Be=(e,t)=>{let n=new Map,r=t??((...s)=>JSON.stringify(s)),o=((...s)=>{let d=r(...s);if(!n.has(d)){let l=e(...s).then(u=>(a(u)&&n.delete(d),u));n.set(d,l)}return n.get(d)});return o.clear=()=>n.clear(),o};import $e from"fs";import ir from"path";import bi from"util";var or=1e3,sr=(e=process.cwd())=>ir.join(ae(e),ne(),"log","epiq.log");function hi(e=process.cwd()){if(!at)return;let t=sr(e);if(!$e.existsSync(t))return;let r=$e.readFileSync(t,"utf8").split(`
2
+ import{McpServer as xs}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as Is}from"@modelcontextprotocol/sdk/server/stdio.js";import{z as S}from"zod";var m={INIT:"init",HELP:"help",NEW:"new",TAG:"tag",MOVE:"move",PEEK:"peek",FILTER:"filter",ASSIGN:"assign",DELETE:"delete",RENAME:"rename",CLOSE_ISSUE:"close",RE_OPEN_ISSUE:"reopen",SET_DESCRIPTION:"edit",SET_EDITOR:"config:editor",SET_VIEW:"config:view",SET_USERNAME:"config:username",SYNC:"sync",NONE:""},oe={None:"none",Invalid:"invalid",Valid:"valid"},ee={None:"none",Success:"success",Fail:"fail"},i=e=>({result:ee.Fail,message:e,data:null}),c=(e,t)=>({result:ee.Success,message:e,data:t}),pn=()=>({result:ee.None,message:"No result",data:null}),a=e=>e.result==="fail";import{ulid as to}from"ulid";import{monotonicFactory as mo,ulid as qe}from"ulid";var Ge=mo(),Je=({name:e,parent:t,user:{userId:n,userName:r}})=>{let o=Ge(),s=Ge(),d=Ge(),l=Ge();return[{id:qe(),userId:n,userName:r,action:"add.issue",payload:{id:o,parent:t,name:e}},{id:qe(),userId:n,userName:r,action:"add.field",payload:{id:s,parent:o,name:"Description",val:""}},{id:qe(),userId:n,userName:r,action:"add.field",payload:{id:d,parent:o,name:"Assignees"}},{id:qe(),userId:n,userName:r,action:"add.field",payload:{id:l,parent:o,name:"Tags"}}]};import Me from"chalk";import{monotonicFactory as gs,ulid as de}from"ulid";import{useSyncExternalStore as Xu}from"react";var P={WORKSPACE:"WORKSPACE",BOARD:"BOARD",SWIMLANE:"SWIMLANE",TICKET:"TICKET",FIELD:"FIELD",FIELD_LIST:"FIELD_LIST",TEXT:"TEXT"};function J(e){return e.context==="TICKET"}var p={DEFAULT:"default",MOVE:"move",HELP:"help",COMMAND_LINE:"command-line"};function Ye(e,t){let n=Math.min(e.length,t.length),r=0;for(;r<n&&e[r]===t[r];)r++;return r}var Xe=e=>typeof e!="string"?"":e.replace(/[\x00-\x08\x0B-\x1F\x7F]/g,"").replace(/[\r\n\t]/g," ").replace(/\s+/g," ").trim();var gn=e=>{let t=new Map;for(let n of e)for(let r=1;r<=n.length;r++){let o=n.slice(0,r),s=t.get(o);s?s.push(n):t.set(o,[n])}return t},fn=(e,t)=>t?e.get(t)??[]:[];var vn=new WeakMap,po=e=>{let t=vn.get(e);return t||(t=gn(e),vn.set(e,t)),t};var yn=({wordList:e,inputToMatch:t,overlapThreshold:n=1})=>{let r=t.toLowerCase();return fn(po(e),r).filter(s=>Ye(r,s)>=n)};var En=({inputToMatch:e,lastWord:t},n)=>{if(t.endsWith(" "))return{hint:"",hints:[],overlap:0,remainder:""};let r=yn({wordList:n,inputToMatch:e,overlapThreshold:1});return go(t,r)},go=(e,t)=>{let n=t[0]??"",r=Ye(e.toLowerCase(),n.toLowerCase()),[o,s]=n.split(":"),d=r<(o??"").length,l=!!s,f=(l&&d?o:n)+(l&&d?":":" "),E=f.slice(r);return{hint:f,hints:t,overlap:r,remainder:E}};var Nn=["vi","vim","nvim","nano","micro","emacs","hx","code","code-insiders","subl","notepad","notepad++","idea","webstorm","default","system","$EDITOR","$VISUAL"];var Ie=24n,fo=Ie*4n,Ze=(1n<<fo)-1n,vo=/^[0-9a-f]+$/;function xn(e){if(!e||!vo.test(e))throw new Error(`Invalid hex rank: ${e}`);return BigInt("0x"+e)}function Qe(e,t=Ie){if(e<0n)throw new Error("Negative rank not allowed");return e.toString(16).padStart(Number(t),"0")}function De(e,t){if(!e&&!t)return Qe(Ze/2n,Ie);let n=e?xn(e):0n,r=t?xn(t):Ze;if(r<=n)return Qe(Ze/2n,Ie);let o=(n+r)/2n;return o===n||o===r?"":Qe(o,Ie)}function Y(){return Qe(Ze/2n,Ie)}var te={workspace:(e,t)=>({id:e,title:t,rank:Y(),isDeleted:!1,props:{},context:P.WORKSPACE,childRenderAxis:"vertical",parentNodeId:null,readonly:!0,log:[]}),board:(e,t,n,r=!1)=>({id:e,title:t,rank:Y(),isDeleted:!1,props:{},context:P.BOARD,childRenderAxis:"horizontal",parentNodeId:n,readonly:r,log:[]}),swimlane:(e,t,n)=>({id:e,title:t,rank:Y(),isDeleted:!1,props:{},context:P.SWIMLANE,childRenderAxis:"vertical",childNavigationAcrossParents:!0,parentNodeId:n,readonly:!1,log:[]}),field:(e,t,n,r={},o="horizontal")=>({id:e,title:t,rank:Y(),isDeleted:!1,props:r,context:P.FIELD,childRenderAxis:o,parentNodeId:n,readonly:!1,log:[]}),ticket:(e,t,n)=>({id:e,title:t,rank:Y(),isDeleted:!1,props:{},context:P.TICKET,childRenderAxis:"vertical",parentNodeId:n,readonly:!1,log:[]}),text:({id:e,name:t,parentNodeId:n,props:r={},readonly:o=!0})=>({id:e,title:t,rank:Y(),isDeleted:!1,props:r,context:P.TEXT,childRenderAxis:"vertical",parentNodeId:n,readonly:o,log:[]})};var V=e=>Object.values(y().nodes).filter(t=>!!t&&!t.isDeleted&&t.parentNodeId===e).sort((t,n)=>t.rank.localeCompare(n.rank)),In=(e,t)=>e.findIndex(n=>n.id===t),Dt=(e,t={at:"end"})=>{if(e.length===0)return c("Resolved rank",Y());switch(t.at){case"start":{let n=e[0];return n?c("Resolved rank",De(void 0,n.rank)):i("Unable to resolve first sibling")}case"end":{let n=e[e.length-1];return n?c("Resolved rank",De(n.rank,void 0)):i("Unable to resolve last sibling")}case"before":{let n=In(e,t.sibling);if(n<0)return i("Sibling not found");let r=n>0?e[n-1]:void 0,o=e[n];return o?c("Resolved rank",De(r?.rank,o.rank)):i("Sibling not found")}case"after":{let n=In(e,t.sibling);if(n<0)return i("Sibling not found");let r=e[n],o=n<e.length-1?e[n+1]:void 0;return r?c("Resolved rank",De(r.rank,o?.rank)):i("Sibling not found")}}};var et=(e,t)=>{let{nodes:n}=y(),r=n[e];if(!r)return i("Node not found");if(r.context===t)return c("Resolved ancestor node",r);let o=r.parentNodeId?n[r.parentNodeId]:void 0;for(;o;){if(o.context===t)return c("Resolved ancestor node",o);o=o.parentNodeId?n[o.parentNodeId]:void 0}return i(`No ancestor found for context: ${t}`)},yo=(e,t)=>{let{nodes:n}=y(),r=n[e];for(;r?.parentNodeId;){if(r.parentNodeId===t)return!0;r=n[r.parentNodeId]}return!1},Ft=(e,t)=>e?e.readonly?i({move:"Cannot move readonly node",rename:"Cannot rename readonly node",edit:"Cannot edit readonly node"}[t]):null:i("Node not found"),N={deleteNode(e){j(t=>{let n={...t.nodes};return delete n[e],{...t,nodes:n}})},editValue(e,t){let{nodes:n}=y(),r=n[e];if(!r)return i("Edit target node not found");let o=Ft(r,"edit");if(o)return o;let s={...r,props:{...r.props,value:t}};return N.updateNode(s),c("Issue description updated",{md:t})},renameNode(e,t){let n=this.getNode(e);if(!n)return i("Rename target node not found");let r=Ft(n,"rename");if(r)return r;let o={...n,title:t};return this.updateNode(o),c("Renamed node",o)},getExistingTags(){let{tags:e}=y();return[...new Set(Object.values(e).map(t=>t.name).filter(Boolean))]},getExistingAssignees(){let{contributors:e}=y();return[...new Set(Object.values(e).map(t=>t.name).filter(Boolean))]},getFieldByTitle(e,t){return V(e).find(n=>n.title===t)},moveNode({id:e,parentId:t,position:n={at:"end"}}){let{rootNodeId:r}=y(),o=this.getNode(e),s=this.getNode(t);if(!o)return i("Node not found");if(!s)return i("Target parent not found");if(r===e)return i("Cannot move root node");if(e===t)return i("Cannot move node into itself");let d=Ft(o,"move");if(d)return d;if(yo(t,e))return i("Cannot move node into its own descendant");let l=V(t).filter(f=>f.id!==e),u=Dt(l,n);if(a(u))return u;let v={...o,parentNodeId:t,rank:u.data};return this.updateNode(v),c("Moved node successfully",v)},tombstoneNode(e){let{nodes:t,currentNodeId:n,rootNodeId:r}=y(),o=this.getNode(e);if(!o)return i("Node not found");if(r===e)return i("Cannot delete root node");let s=new Set,d=u=>{let v=t[u];if(!(!v||s.has(u))){s.add(u);for(let f of V(v.id))d(f.id)}};d(e);let l={...structuredClone(t)};for(let u of s){if(!l[u])return i("Unable to locate node to delete");l[u]={...l[u],isDeleted:!0}}return n?(I({nodes:l}),c("Successfully tomb stoned",o)):i("Unable to delete undefined")},createContributor(e){let t=j(n=>({...n,contributors:{...n.contributors,[e.id]:e}}));return a(t)?i("Unable to create contributor"):c("Created contributor",e)},assign(e,t,n){let r=N.getContributor(t),o=N.getNode(e);if(!o||!r)return i("Unable assign contributor to issue");let s=this.getFieldByTitle(o.id,"Assignees");if(!s)return i("Unable to locate assignees field");if(V(s.id).some(u=>u.props?.value===t))return i("Contributor already assigned");let l=this.createNodeAtPosition(te.field(n,r.name,s.id,{value:t}));return a(l)?l:c("Assigned contributor",l.data)},createTag(e){let t=j(n=>({...n,tags:{...n.tags,[e.id]:e}}));return a(t)?i("Could not create tag"):c("Tag created",e)},tag(e,t,n){let r=N.getTag(t),o=N.getNode(e);if(!r)return i("Unable to add tag, missing tag");if(!o)return i("Unable to add tag, missing target");let s=this.getFieldByTitle(o.id,"Tags");if(!s)return i("Unable to locate tags field");if(V(s.id).some(u=>u.props?.value===t))return i("Tag already assigned");let l=this.createNodeAtPosition(te.field(n,r.name,s.id,{value:t}));return a(l)?l:c("Tag added",l.data)},createNodeAtPosition(e,t={at:"end"}){if(!e.parentNodeId){let s={...e,rank:Y()};return this.createNode(s),c("Created node",s)}let n=V(e.parentNodeId),r=Dt(n,t);if(a(r))return r;let o={...e,rank:r.data};return this.createNode(o),c("Created node",o)},createNode(e){let t=j(n=>({...n,nodes:{...n.nodes,[e.id]:e}}));return a(t)?i("Unable to create node"):c("Node created",e)},lockNode(e){let t=this.getNode(e);if(!t)return i("Failed to locate node");let n={...t,readonly:!0},r=j(o=>({...o,nodes:{...o.nodes,[e]:n}}));return a(r)?i(r.message):c("Locked node",n)},updateNode(e){let t=j(n=>({...n,nodes:{...n.nodes,[e.id]:e}}));return a(t)?t:c("Updated node",e)},getContributor(e){return y().contributors[e]},getTag(e){return y().tags[e]},getNode(e){return y().nodes[e]},getSiblings:e=>Object.values(y().nodes).filter(t=>!t.isDeleted&&t.parentNodeId===e).sort((t,n)=>t.rank.localeCompare(n.rank))};var tt={autoSync:!1,preferredEditor:null,userName:null,userId:null},ie=()=>tt,nt=e=>(tt={...tt,...e},tt);var Cn=()=>{let e=ie(),t=!!e.userName?.trim(),n=!!e.preferredEditor?.trim();return{isSetup:n&&t,hasPreferredEditor:n,hasUserName:t,userName:e.userName,preferredEditor:e.preferredEditor}},bn=()=>!Fe();var W={bg:"#1a1b26",fg:"#c8d3ff",grayDark:"#2a2f45",gray:"#46507a",grayLight:"#969bb5",cyan:"#88d5ee",cyanSoft:"#8fe6fb",blue:"#5b8cff",magenta:"#a78bfa",magentaSoft:"#c4b5fd",green:"#8fdc8c",yellow:"#f1c27d",red:"#ff7a90",white:"#ffffff"},hn={accent:W.cyan,accent2:W.magenta,primary:W.white,secondary:W.grayDark,secondary2:W.grayLight,gray:W.gray,green:W.green,yellow:W.yellow,red:W.red};var g={red:W.red,yellow:W.yellow,green:W.green,blue:W.blue,magenta:W.magenta,cyan:W.cyan},rt={urgent:g.red,critical:g.red,important:g.red,blocker:g.red,asap:g.red,immediate:g.red,fail:g.red,failure:g.red,broken:g.red,bug:g.red,error:g.red,incident:g.red,outage:g.red,production:g.red,crash:g.red,security:g.red,warning:g.yellow,warn:g.yellow,risky:g.yellow,risk:g.yellow,attention:g.yellow,pending:g.yellow,review:g.yellow,"needs-review":g.yellow,qa:g.yellow,testing:g.yellow,test:g.yellow,validate:g.yellow,verification:g.yellow,staging:g.yellow,check:g.yellow,"follow-up":g.yellow,followup:g.yellow,waiting:g.yellow,blocked:g.yellow,hold:g.yellow,done:g.green,complete:g.green,completed:g.green,success:g.green,ok:g.green,stable:g.green,resolved:g.green,fixed:g.green,closed:g.green,merged:g.green,released:g.green,deployed:g.green,approved:g.green,verified:g.green,working:g.green,healthy:g.green,pass:g.green,passing:g.green,info:g.blue,information:g.blue,note:g.blue,docs:g.blue,documentation:g.blue,doc:g.blue,guide:g.blue,help:g.blue,explanation:g.blue,detail:g.blue,details:g.blue,context:g.blue,design:g.blue,discussion:g.blue,proposal:g.blue,idea:g.blue,feature:g.magenta,enhancement:g.magenta,improvement:g.magenta,refactor:g.magenta,refactoring:g.magenta,cleanup:g.magenta,optimize:g.magenta,optimization:g.magenta,perf:g.magenta,performance:g.magenta,upgrade:g.magenta,migration:g.magenta,modernize:g.magenta,debt:g.magenta,todo:g.cyan,next:g.cyan,planned:g.cyan,plan:g.cyan,future:g.cyan,backlog:g.cyan,investigate:g.cyan,explore:g.cyan,prototype:g.cyan};var Eo=/^(\d+)(h|d|w|mo|y)$/,No=/^(\d{4})-(\d{2})-(\d{2})(?:(?::|\s)(\d{2}):(\d{2}))?$/,xo=({year:e,month:t,day:n,hour:r=0,minute:o=0})=>{let s=new Date(e,t-1,n,r,o);return s.getFullYear()===e&&s.getMonth()===t-1&&s.getDate()===n&&s.getHours()===r&&s.getMinutes()===o},Io=(e,t=new Date)=>{let n=e.match(Eo);if(!n)return null;let[,r,o]=n,s=Number(r);if(!Number.isInteger(s)||s<=0)return null;let d=new Date(t);switch(o){case"h":return d.setHours(d.getHours()-s),d;case"d":return d.setDate(d.getDate()-s),d;case"w":return d.setDate(d.getDate()-s*7),d;case"mo":return d.setMonth(d.getMonth()-s),d;case"y":return d.setFullYear(d.getFullYear()-s),d;default:return null}},Co=e=>{let t=e.match(No);if(!t)return null;let[,n,r,o,s,d]=t,l=Number(n),u=Number(r),v=Number(o),f=s?Number(s):0,E=d?Number(d):0;return xo({year:l,month:u,day:v,hour:f,minute:E})?new Date(l,u-1,v,f,E):null},ot=e=>{let t=e.trim().toLowerCase();return Io(t)??Co(t)},Rn=({date:e,horizonDate:t})=>t?e.getTime()>=t.getTime():!0,bo=[{unit:"h",from:1,to:24},{unit:"d",from:1,to:7},{unit:"w",from:1,to:52},{unit:"mo",from:1,to:12},{unit:"y",from:1,to:5}],Sn=(e=bo)=>{let t=[];for(let{unit:n,from:r,to:o}of e)for(let s=r;s<=o;s++)t.push(`${s}${n}`);return t};var ho=["BOARD","TICKET","SWIMLANE"],_=e=>{let{currentNode:t,readOnly:n,selectedNode:r}=y(),o=Cn().isSetup,s=t.context,d=r?.context,l=[m.SYNC,m.HELP,m.SET_VIEW,m.SET_EDITOR,m.SET_USERNAME],u=[m.NEW,m.RENAME,m.DELETE],v=[m.TAG,m.ASSIGN,m.CLOSE_ISSUE,m.RE_OPEN_ISSUE,m.SET_DESCRIPTION],f=[m.FILTER,m.PEEK],E={WORKSPACE:[...l,...u],BOARD:[...f,...l,...u],SWIMLANE:[...f,...l,...u],TICKET:[...l,...u,...v],FIELD:[...l,...v],FIELD_LIST:[...l,...v],TEXT:[...l]},C=d&&ho.includes(d),R=[...E[s||"WORKSPACE"]].filter(Q=>[m.RENAME,m.DELETE,m.MOVE].includes(Q)?C:!0),M={[m.PEEK]:[...Sn(),"now","prev","next"],[m.SYNC]:[],[m.INIT]:[],[m.SET_USERNAME]:[],[m.SET_DESCRIPTION]:["confirm"],[m.DELETE]:["confirm"],[m.RE_OPEN_ISSUE]:["confirm"],[m.MOVE]:["start","confirm","next","previous","to-next","to-previous","cancel"],[m.CLOSE_ISSUE]:["confirm"],[m.FILTER]:["tag","assignee","description","title","clear"],[m.SET_VIEW]:["dense","wide"],[m.SET_EDITOR]:[...Nn,"vim"],[m.TAG]:[...new Set([...Object.keys(rt),...N.getExistingTags()])],[m.ASSIGN]:N.getExistingAssignees(),[m.HELP]:[],[m.RENAME]:[],[m.NEW]:s==="TICKET"||s==="FIELD"||s==="FIELD_LIST"?["issue","swimlane","board"]:s==="SWIMLANE"?["issue","swimlane","board"]:s==="BOARD"?["issue","swimlane","board"]:["board"],[m.NONE]:R};return o?bn()?n&&(M={[m.NONE]:[m.HELP,m.PEEK],[m.HELP]:M[m.HELP],[m.PEEK]:M[m.PEEK]}):M={[m.NONE]:[m.HELP,m.INIT],[m.HELP]:M[m.HELP],[m.INIT]:M[m.INIT]}:M={[m.NONE]:[m.HELP,m.SET_EDITOR,m.SET_USERNAME],[m.HELP]:M[m.HELP],[m.SET_EDITOR]:M[m.SET_EDITOR],[m.SET_USERNAME]:M[m.SET_USERNAME]},M[e]??[]};import st from"chalk";import{decodeTime as An}from"ulid";var wn=e=>{try{return c("Decoded date",new Date(An(e)))}catch(t){return i("Decoding failed + "+t.message)}},kt=e=>{if(!e?.id)return null;try{return An(e.id)}catch{return null}};var ve=(e,t)=>{let n=e.find(r=>r.context===t);return n!==void 0?c("Found node",n):i("Unable to find node in breadcrumb")};import Tn from"chalk";var Ut={stringColor:{saturation:50,lightness:60},gradient:{stops:[[174,150,240],[92,138,232],[102,204,226]]}},Ro=(e,t,n)=>Math.max(t,Math.min(n,e)),Ot=(e,t,n)=>e+(t-e)*n,Mn=e=>{let t=0;for(let n=0;n<e.length;n++)t=t*31+e.charCodeAt(n)>>>0;return t},So=(e,t,n)=>{let r=t/100,o=n/100,s=(1-Math.abs(2*o-1))*r,d=e/60,l=s*(1-Math.abs(d%2-1)),u=0,v=0,f=0;d>=0&&d<1?(u=s,v=l):d>=1&&d<2?(u=l,v=s):d>=2&&d<3?(v=s,f=l):d>=3&&d<4?(v=l,f=s):d>=4&&d<5?(u=l,f=s):(u=s,f=l);let E=o-s/2;return[Math.round((u+E)*255),Math.round((v+E)*255),Math.round((f+E)*255)]},Ao=([e,t,n])=>`#${e.toString(16).padStart(2,"0")}${t.toString(16).padStart(2,"0")}${n.toString(16).padStart(2,"0")}`,wo=(e,t,n)=>[Math.round(Ot(e[0],t[0],n)),Math.round(Ot(e[1],t[1],n)),Math.round(Ot(e[2],t[2],n))],To=e=>{let n=Mn(e)%360,r=So(n,Ut.stringColor.saturation,Ut.stringColor.lightness);return Ao(r)},Mo=e=>{let t=Ut.gradient.stops,n=Ro(e,0,1);if(t.length===0)return[0,0,0];if(t.length===1)return t[0];let r=t.length-1,o=n*r,s=Math.min(Math.floor(o),r-1),d=o-s;return wo(t[s],t[s+1],d)},it=e=>Mn(e.toLowerCase().trim())/4294967295,Lo=e=>{let t=it(e);return Mo(t)},Po=e=>{let[t,n,r]=Lo(e);return{normal:o=>Tn.bgRgb(t,n,r).black(o),cursor:o=>Tn.bgRgb(t,n,r).white.bold(o)}};var _t=e=>Po(e).normal(` ${e} `),Wt=(e,t=rt)=>{let r=(o=>o.toLowerCase().trim())(e);return r&&t[r]?t[r]:To(r)};var Do=["BOARD","TICKET","SWIMLANE"],Bt=()=>{let e=y().selectedNode;return e?.context?Do.includes(e?.context)?F():U({message:"Command not available in this context",completionWordList:[]}):U({message:"Missing target context",completionWordList:[]})},z="<ENTER> to confirm",F=(e="",t=[])=>({message:e,validity:oe.Valid,completionWordList:t}),U=({message:e,completionWordList:t})=>({validity:oe.Invalid,message:e,completionWordList:t}),ke=e=>e.length===0,me=({prefix:e="",wordList:t,postfix:n="",noOfHints:r=100,inputString:o,minLengthForHints:s=1})=>{let u=[...t.filter(Boolean).filter(f=>f.startsWith(o.trim()))].sort((f,E)=>it(f)-it(E)).slice(0,r).map(_t),v=u.length>s?u.join(" "):"";return v?`${e}${v}${n}`:""},$t=({modifier:e})=>{let t="confirm";return e===t?F(z):U({message:ke(e)?`if you are certain, enter ${_t(t)}`:"",completionWordList:[t]})},Fo=({list:e,hint:t})=>({modifier:n})=>e.includes(n)?F(z):U({message:ke(n)?t:"",completionWordList:[]}),ko=({list:e,hint:t,onValue:n})=>({modifier:r,inputString:o})=>e.includes(r)?o.trim().length<1?U({message:n,completionWordList:[]}):F():U({message:ke(r)?t:"",completionWordList:[]}),Ht=({hint:e})=>({modifier:t,inputString:n})=>ke(t)&&ke(n)?U({message:e,completionWordList:[]}):F(z),Oo={[m.PEEK]:e=>{let t=e.modifier;if(t==="now")return F(z);let n={message:"historical state from: '1h', '2d', '23h', '1mo', '2y', 'previous', 'next' or full date as YYYY-MM-DD",completionWordList:[]};if(t==="prev"||t==="next")return F(z);let r=ot(t);if(!t||!r)return U(n);let o=ve(y().breadCrumb,"BOARD");if(a(o))return U({message:"Command is not applicable in this context",completionWordList:[]});let s=wn(o.data.id);return a(s)?U({message:"Unable to peek: board id is not a valid ULID",completionWordList:[]}):Rn({date:r,horizonDate:s.data})?F(z):U({message:st.red(`nothing to peek before ${s.data.toISOString().slice(0,16).replace("T"," ")}`),completionWordList:[]})},[m.INIT]:()=>F(z),[m.FILTER]:e=>{if(e.modifier==="clear")return F();let t=d=>_(m.FILTER).includes(d);if(!e.modifier||!t(e.modifier??""))return U({message:me({wordList:_(m.FILTER),inputString:e.inputString}),completionWordList:_(m.FILTER)});let r=Object.values(y().tags).map(d=>d.name),o=Object.values(y().contributors).map(d=>d.name),s=e.modifier==="tag"?r:e.modifier==="assignee"?o:[];return e.inputString?s.length&&!s.includes(e.inputString.trim()??"")?U({message:me({prefix:`existing ${e.modifier}s... `,wordList:s,noOfHints:10,inputString:e.inputString}),completionWordList:s}):F():U({message:me({prefix:"one of... ",wordList:s,noOfHints:10,inputString:e.inputString}),completionWordList:s})},[m.NONE]:e=>{let t=_(m.NONE),n=/^[A-Za-z_]+:/g,r=e.inputString.match(n);return r&&r.length?t=[...t.filter(o=>o.trim().match(n))]:t=[...new Set(t.flatMap(o=>o.match(n)?.join("").replace(":","")??o))],e.command?F():U({message:me({prefix:"... ",wordList:t,inputString:e.inputString,minLengthForHints:0}),completionWordList:[]})},[m.NEW]:e=>ko({list:_(m.NEW),hint:me({wordList:_(m.NEW),noOfHints:3,inputString:e.inputString,minLengthForHints:0}),onValue:"provide a name..."})(e),[m.SET_DESCRIPTION]:()=>F(z),[m.HELP]:()=>F(z),[m.RENAME]:()=>{let e=Bt();return e.validity==="invalid"?e:F(z)},[m.DELETE]:e=>{let t=Bt();return t.validity==="invalid"?t:$t(e)},[m.CLOSE_ISSUE]:e=>$t(e),[m.RE_OPEN_ISSUE]:e=>$t(e),[m.MOVE]:e=>{let t=Bt();return t.validity==="invalid"?t:Ht({hint:me({prefix:"hey hacker! These commands are blocked for you... ",wordList:_(m.MOVE),noOfHints:10,inputString:e.inputString})})(e)},[m.TAG]:e=>{let t=N.getExistingTags().map(n=>` ${st.bgHex(Wt(n))(" "+n+" ")} `).slice(0,10);return Ht({hint:"tag name like... "+t.join("")})(e)},[m.ASSIGN]:e=>{let t=N.getExistingAssignees().map(n=>` ${st.bgHex(Wt(n))(" "+n+" ")} `).slice(0,10);return Ht({hint:"assign to... "+t.join("")})(e)},[m.SET_EDITOR]:e=>{logger.debug(`Validating command: ${e.command} ${e.modifier} ${e.inputString}`);let t=_(m.SET_EDITOR);return e.modifier?F(z):U({message:me({wordList:t,inputString:e.inputString}),completionWordList:[]})},[m.SET_USERNAME]:e=>e.inputString?F():U({message:`Enter a username. Saved in ${st.bgBlack("~/.epiq/")}`,completionWordList:[]}),[m.SET_VIEW]:e=>Fo({list:_(m.SET_VIEW),hint:me({wordList:_(m.SET_VIEW),noOfHints:3,inputString:e.inputString})})(e),[m.SYNC]:()=>F(z)},Ln=Object.fromEntries(Object.entries(Oo).map(([e,t])=>[e,{validate:(n,r,o)=>t({modifier:r,command:n,inputString:o})}]));var Pn=["frontend","backend","infrastructure","architecture","integration","configuration","implementation","application","deployment","environment","framework","platform","service","component","module","gateway","pipeline","containerization","orchestrator","exception","incident","defect","regression","degradation","malfunction","instability","intermittent","reproducibility","reproduction","investigation","triage","workaround","mitigation","remediation","optimization","stabilization","refinement","failure","outage","blocking","criticality","severity","escalation","diagnostics","analysis","resolution","corruption","inconsistency","validation","verification","authorization","authentication","confidentiality","availability","accessibility","reliability","compliance","governance","encryption","decryption","integrity","auditing","traceability","accountability","protection","privileges","permissions","dependency","orchestration","provisioning","synchronization","compatibility","incompatibility","interoperability","observability","instrumentation","telemetry","loadbalancing","discovery","registration","scheduling","coordination","distribution","isolation","virtualization","serialization","deserialization","initialization","instantiation","propagation","aggregation","consolidation","normalization","standardization","transformation","reconciliation","correlation","processing","indexing","partitioning","enrichment","validation","filtering","streaming","batching","concurrency","parallelism","contention","deadlock","throttling","ratelimiting","backpressure","fragmentation","saturation","exhaustion","partitioning","replication","redundancy","failover","deprecation","obsolescence","starvation","overload","underutilization","latency","throughput","refactoring","modularization","encapsulation","abstraction","extensibility","configurability","maintainability","recoverability","sustainability","readability","testability","debuggability","reusability","simplicity","consistency","performance","functionality","requirement","recommendation","improvement","enhancement","clarification","documentation","description","acceptance","criteria","estimation","prioritization","dependency","deliverable","milestone","iteration"];var b={Init:"init",None:"none",ViewHelp:"view-help",Rename:"rename",Edit:"edit",Delete:"delete",Filter:"filter",Move:"move",Peek:"peek",SetView:"set-view",SetEditor:"set-editor",SetUserName:"set-user-name",SetAutoSync:"set-auto-sync",NewItem:"add-new-item",TagTicket:"ticket-tag",AssignUserToTicket:"ticket-assign-user",CloseIssue:"close-issue",ReopenIssue:"re-open-issue",Sync:"sync"};var Dn=e=>Object.values(m).includes(e),Fn=(e,t)=>{let n=e.command??"",{modifier:r,target:o,inputString:s}=e,{message:d,validity:l,completionWordList:u}=Ln[n].validate(n,r,s),v=o==="command"?Object.values(m):n&&e.target==="modifier"?_(n):Pn;return{validity:l,command:e.command,modifier:e.modifier,inputString:e.inputString,infoMessage:d??"",autoCompletion:t?En(e,[...u,...v]):{hint:"",hints:[],remainder:"",overlap:0}}};var kn=e=>{let t=e.trimStart(),n=_o(t),r=(n[0]??"").trimStart().trimEnd(),o=(n[1]??"").trimStart().trimEnd(),s=Wo(e),d=Dn(r)?r:null,l=d!==null,u=r!=="",v=e.endsWith(" "),f=d?_(d)??[]:[],E=d&&f.includes(o)?o:"",C="word";n.length<=1?C="command":n.length===2&&(C="modifier");let R=Uo(t,d,E);return{raw:e,trimmedStart:t,words:n,firstWord:r,lastWord:s,hasCommand:u,command:d,isCommandKeyword:l,isLastWordCompleted:v,modifier:E,target:C,inputToMatch:s,inputString:R}},Uo=(e,t,n)=>{let r=e;return t&&r.startsWith(t)&&(r=r.slice(t.length)),r=r.replace(/^\s+/,""),n&&r.startsWith(n)&&(r=r.slice(n.length),r=r.replace(/^\s+/,"")),r},_o=e=>e?e.split(/\s+/):[],Wo=e=>e.trimEnd().split(/\s+/).at(-1)??"";var On=" ",Ce={commandHistory:[],value:"",commandHistoryIndex:-1,cursorPosition:0,commandIsPending:!1,commandMeta:{command:null,modifier:"",infoMessage:"",inputString:"",validity:oe.None,autoCompletion:{hint:"",hints:[],remainder:"",overlap:0}}},Bo=new Set,Un=()=>{for(let e of Bo)e()};var se=e=>{let n=e(Ce),r=kn(n.value),o=n.cursorPosition===n.value.length;Ce={...n,commandMeta:Fn(r,o)},Un()},Oe=({message:e,result:t})=>{let n=structuredClone(Ce);return n.commandMeta={...n.commandMeta,infoMessage:e??"",validity:t==="fail"?"invalid":"valid"},n.commandIsPending=!0,Ce=n,Un(),c(e,null)},Kt=e=>{se(t=>({...t,cursorPosition:Math.max(0,Math.min(t.value.length,t.cursorPosition+e))}))},Vt=e=>{se(t=>{let{value:n,cursorPosition:r}=t,o=r;if(e==="left"){for(;o>0&&n[o-1]===" ";)o--;for(;o>0&&n[o-1]!==" ";)o--}else{for(;o<n.length&&n[o]!==" ";)o++;for(;o<n.length&&n[o]===" ";)o++}return{...t,cursorPosition:o}})},_n=()=>{se(e=>{let t=e.value.slice(e.cursorPosition),n=Math.max(0,e.cursorPosition-1);return{...e,value:e.value.slice(0,n)+t,cursorPosition:n,commandIsPending:!1}})},Wn=()=>{se(e=>{let{value:t,cursorPosition:n}=e,r=n;for(;r>0&&t[r-1]===" ";)r--;for(;r>0&&t[r-1]!==" ";)r--;let o=t.slice(n);return{...e,value:t.slice(0,r)+o,cursorPosition:r,commandIsPending:!1}})},k=e=>{se(t=>{let n=Math.max(0,Math.min(t.cursorPosition,t.value.length)),r=t.value.slice(0,n),o=t.value.slice(n),s=e(r,t.commandMeta.autoCompletion),d=s+o,l=Math.max(0,Math.min(s.length,d.length));return{...t,value:d,cursorPosition:l,commandIsPending:!1}})},Bn=()=>{se(e=>({...e,commandIsPending:!0}))},$n=({addToHistory:e=!0})=>{se(n=>({...n,commandHistory:e?[n.value,...n.commandHistory].slice(0,40):n.commandHistory,commandHistoryIndex:-1,commandIsPending:!1})),$o()},Hn=()=>{se(e=>{let t=Math.min(e.commandHistoryIndex+1,e.commandHistory.length-1),n=e.commandHistory[t]??"";return{...e,commandHistoryIndex:t,value:n,cursorPosition:n.length}})},Kn=()=>{se(e=>{let t=Math.max(e.commandHistoryIndex-1,-1),n=t===-1?"":e.commandHistory[t]??"";return{...e,commandHistoryIndex:t,value:n,cursorPosition:n.length}})},$o=()=>k(()=>""),X=()=>Ce,at=()=>{let[e,...t]=Ce.value.split(On);return t.join(On).trim()};var h={Sync:"sync",NavPreviousItem:"navPreviousItem",NavNextItem:"navNextItem",NavToPreviousContainer:"navToPreviousContainer",NavToNextContainer:"navToNextContainer",MovePreviousItem:"movePreviousItem",MoveNextItem:"moveNextItem",MoveToPreviousContainer:"moveToPreviousContainer",MoveToNextContainer:"moveToNextContainer",Confirm:"confirm",Exit:"exit",ViewHelp:"viewHelp",HideHelp:"hideHelp",InitMove:"initMove",ConfirmMove:"confirmMove",Delete:"Delete",InitCommandLine:"initCommandLine",ExitCommandLine:"exitCommandLine",CaptureInput:"captureInput",EraseInput:"eraseInput",AddItem:"addItem",GetLastCommandFromHistory:"getLastCommandFromHistory",GetNextCommandFromHistory:"getNextCommandFromHistory",AutoCompleteCommand:"autoCompleteCommand",MoveCursorLeft:"MoveCursorLeft",MoveCursorRight:"MoveCursorRight",MoveCursorLeftOfWord:"MoveCursorLeftOfWord",MoveCursorRightOfWord:"MoveCursorRightOfWord",EraseInputWord:"EraseInputWord",None:"None",Edit:"edit",SetViewDense:"SetViewDense",SetViewWide:"SetViewWide"};var Vn=e=>{let{context:t}=y()?.currentNode;if(!t)return b.None;switch(e){case m.INIT:return b.Init;case m.DELETE:return b.Delete;case m.SET_DESCRIPTION:return b.Edit;case m.HELP:return b.ViewHelp;case m.RE_OPEN_ISSUE:return b.ReopenIssue;case m.CLOSE_ISSUE:return b.CloseIssue;case m.TAG:return b.TagTicket;case m.ASSIGN:return b.AssignUserToTicket;case m.RENAME:return b.Rename;case m.NEW:return b.NewItem;case m.FILTER:return b.Filter;case m.MOVE:return b.Move;case m.PEEK:return b.Peek;case m.SET_USERNAME:return b.SetUserName;case m.SET_EDITOR:return b.SetEditor;case m.SET_VIEW:return b.SetView;case m.SYNC:return b.Sync;default:return b.None}};import{ulid as D}from"ulid";import{spawnSync as Jo}from"node:child_process";import Yo from"node:os";import Gn from"node:path";import{ulid as Xo}from"ulid";import{accessSync as Ho,copyFileSync as Ko,existsSync as dt,mkdirSync as jn,readdirSync as zn,readFileSync as Vo,renameSync as jo,rmSync as zo,statSync as qn,unlinkSync as qo,writeFileSync as Go}from"node:fs";import be from"node:path";var q={writeToFile:(e,t)=>{try{let n=be.dirname(e);dt(n)||jn(n,{recursive:!0});let r=typeof t=="string"?t:JSON.stringify(t,null,2);Go(e,r,"utf-8")}catch(n){logger.error(`Failed to write file at ${e}:`,n)}},readFile:e=>{try{return Vo(e,"utf-8")}catch(t){return logger.error(`Failed to read file at ${e}:`,t),null}},readFileJSON(e){try{let t=q.readFile(e);return t===null?null:JSON.parse(t)}catch(t){return logger.error(`Failed to read JSON at ${e}:`,t),null}},dirExists:e=>{try{return dt(e)&&qn(e).isDirectory()}catch{return!1}},async fileExists(e){try{return await Ho(e),!0}catch{return!1}},mkDir:e=>jn(e,{recursive:!0}),locateFolder:e=>{let t=process.cwd(),{root:n}=be.parse(t);for(;;){let r=be.join(t,e);try{if(dt(r)&&qn(r).isDirectory())return r}catch{logger.error(`Unable to locate folder ${e}`)}if(t===n)break;t=be.dirname(t)}return null},readFirstJSON(e){try{if(!q.dirExists(e))return null;let t=zn(e).filter(r=>r.endsWith(".json")).sort()[0];if(!t)return null;let n=be.join(e,t);return q.readFileJSON(n)}catch(t){return logger.error(`Could not read first JSON in folder ${e}`,t),null}},listDir:e=>{try{return q.dirExists(e)?zn(e):[]}catch(t){return logger.error(`Failed to list dir ${e}`,t),[]}},rmFile(e){try{qo(e)}catch(t){t?.code!=="ENOENT"&&logger.error(`Unable to remove file ${e}`)}},rmDir(e){try{zo(e,{recursive:!0,force:!0})}catch(t){t?.code!=="ENOENT"&&logger.error(`Unable to remove dir ${e}`)}},moveFile(e,t,n){if(this.mkDir(be.dirname(t)),!n?.overwrite&&dt(t))throw new Error(`moveFile: destination exists: ${t}`);n?.overwrite&&this.rmFile(t);try{jo(e,t)}catch(r){if(r?.code==="EXDEV"){Ko(e,t),this.rmFile(e);return}throw r}}};function Zo(){let{preferredEditor:e}=ie(),t=[e,process.env.VISUAL,process.env.EDITOR,"vim","vi","nano"].filter(n=>!!n?.trim());return[...new Set(t)]}function Qo(e,t){return/(^|\/)code(-insiders)?$/.test(e.trim())?`${e} --wait "${t}"`:`${e} "${t}"`}function Jn(e){let t=Gn.join(Yo.tmpdir(),"epiq");q.mkDir(t);let n=Gn.join(t,Xo());q.writeToFile(n,e??"");let r=Zo();for(let o of r){let s=Qo(o,n),d=Jo(s,{stdio:"inherit",shell:!0});if(!d.error&&d.status===0){let l=q.readFile(n);if(l==null)return i("Unable to read edited file");let u=l.replace(/\r?\n$/,"");return c("Successfully edited",u)}}return i("Unable to open editor")}import pt from"node:fs";import gt from"node:path";import{z as zt}from"zod";var ct=process.env.IS_LOCAL==="true",ne=()=>".epiq";import lt from"node:fs";import ye from"node:path";import{decodeTime as ei,monotonicFactory as ti}from"ulid";import{z as Ue}from"zod";var Yn=e=>({action:e.action,payload:e.payload});var Zn=1,Xn=ti(),ni="events",ri=Ue.tuple([Ue.string().min(1),Ue.string().min(1).nullable()]),oi=Ue.looseObject({v:Ue.literal(Zn),id:ri}),jt=e=>{let t=oi.safeParse(e);return t.success?c("Parsed persisted event",t.data):i(`Invalid persisted event: ${t.error.issues.map(n=>n.path.join(".")||n.message).join(", ")}`)},ut=e=>e.trim().toLowerCase().replace(/[^a-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||"unknown",H=()=>{let{userName:e,userId:t}=ie();return e?t?e.trim()?c("Successfully resolved actor ID",{userId:ut(t),userName:ut(e)}):i("Unable to resolve actor ID from settings or OS user info"):i("User ID not configured"):i("User name not configured")},ii=e=>lt.existsSync(ye.join(e,ne()))&&lt.statSync(ye.join(e,ne())).isDirectory(),ae=(e=process.cwd())=>{let t=ye.resolve(e);for(;;){if(ii(t))return t;let n=ye.dirname(t);if(n===t)return ye.resolve(e);t=n}},Qn=(e=process.cwd())=>ye.join(ae(e),ne(),ni),_e=({userId:e,userName:t})=>`${ut(e)}.${ut(t)}.jsonl`,si=(e=process.cwd(),{userId:t,userName:n})=>{let r=_e({userId:t,userName:n});return/^(?!.*\.jsonl.*\.jsonl).*\.jsonl$/.test(r)?c("Successfully resolved event log path",ye.join(Qn(e),r)):i(`Invalid event log file name: ${r}`)},ai=(e,t)=>{let n={[e.action]:e.payload,v:Zn,id:t};return jt(n)};function mt({event:e,rootDir:t=process.cwd()}){try{let n=ae(t),r=Qn(n),o=si(n,{userId:e.userId,userName:e.userName});if(a(o))return o;lt.mkdirSync(r,{recursive:!0});let s=er(n);if(a(s))return i(s.message);let d;if(s.data){let u=ei(s.data),v=Math.max(Date.now(),u+1);d=Xn(v)}else d=Xn();let l=ai(Yn(e),[d,s.data]);return a(l)?i(l.message):(lt.appendFileSync(o.data,`${JSON.stringify(l.data)}
3
+ `,"utf8"),c("Event persisted",{path:o.data,entry:l.data}))}catch(n){let r=n instanceof Error?n.message:"Unknown persist error";return i(`Failed to persist event: ${r}`)}}import{decodeTime as di}from"ulid";var ci=ne(),li="events",ui=zt.object({userId:zt.string().min(1).default("unknown"),userName:zt.string().min(1).default("unknown")}),mi=(e=process.cwd())=>gt.join(ae(e),ci,li),pi=e=>{let[t,n]=gt.basename(e,".jsonl").split("."),r=ui.safeParse({userId:t,userName:n});return r.success?c("Parsed event file actor",r.data):i(`Invalid event file name ${gt.basename(e)}: ${r.error.issues.map(o=>o.path.join(".")||o.message).join(", ")}`)},gi=e=>{let t=Object.keys(e).filter(n=>n!=="id"&&n!=="v");return t.length!==1?i(`Invalid persisted event: expected exactly 1 action key, got ${t.length}`):!t[0]||!(t[0]in e)?i("Invalid persisted event: action key is missing or invalid"):c("Resolved persisted action",t[0])},fi=(e,t)=>t in e,vi=({id:e,action:t,payload:n,userId:r,userName:o})=>({id:e,action:t,payload:n,userId:r,userName:o}),yi=e=>{let{userId:t,userName:n,...r}=e,o=gi(r);if(a(o))return i(o.message);let s=o.data,d=e.id?.[0];return d?fi(r,s)?c("Decoded persisted event",vi({id:d,action:s,payload:r[s],userId:t,userName:n})):i(`Persisted event is missing payload for action: ${s}`):i("Persisted event is missing id")},ft=e=>{if(!pt.existsSync(e))return c("Event file missing",[]);let t=pi(e);if(a(t))return i(t.message);let n=pt.readFileSync(e,"utf8"),r=[];for(let o of n.split(`
4
+ `)){let s=o.trim();if(!s)continue;let d;try{d=JSON.parse(s)}catch{return i(`Failed to parse event JSON from ${e}: ${s}`)}let l=jt(d);if(a(l))return i(`${l.message} in ${e}: ${s}`);r.push({...l.data,userId:t.data.userId,userName:t.data.userName})}return c("Parsed persisted events file",r)};function tr(e=process.cwd()){let t=mi(e);if(!pt.existsSync(t))return i("No events found");let n=pt.readdirSync(t).filter(o=>o.endsWith(".jsonl")).map(o=>gt.join(t,o)),r=[];for(let o of n){let s=ft(o);if(a(s))return i(s.message);r.push(...s.data)}return c("All events loaded",Ei(r))}function We(e=process.cwd()){let t=tr(e);if(a(t))return i(t.message);let n=[];for(let r of t.data){let o=yi(r);if(a(o))return i(`Failed to decode event ${r.id?.[0]??"<unknown>"}: ${o.message}`);n.push(o.data)}return c("Loaded merged events",n)}function er(e=process.cwd()){let t=tr(e);return a(t)?i(t.message):c("Loaded edge reference",t.data.at(-1)?.id?.[0]??null)}var Ei=e=>{let t=new Map(e.map(l=>[l.id[0],l])),n=new Map;for(let l of e){let u=l.id[1],v=n.get(u)??[];v.push(l),n.set(u,v)}for(let l of n.values())l.sort((u,v)=>{let[f]=u.id,[E]=v.id;return f.localeCompare(E)});let r=[],o=new Set,s=l=>{let u=n.get(l)??[];for(let v of u){let[f]=v.id;o.has(f)||(o.add(f),r.push(v),s(f))}};s(null);let d=[...e].filter(l=>{let[u]=l.id;return!o.has(u)}).sort((l,u)=>{let[v,f]=l.id,[E,C]=u.id,R=f===null||t.has(f),M=C===null||t.has(C);if(R&&!M)return-1;if(!R&&M)return 1;let Q=(f??"").localeCompare(C??"");return Q!==0?Q:v.localeCompare(E)});return[...r,...d]},nr=(e,t)=>{let n=e.findIndex(r=>{try{return di(r.id)>t}catch{return!0}});return n===-1?{appliedEvents:e,unappliedEvents:[]}:{appliedEvents:e.slice(0,n),unappliedEvents:e.slice(n)}};var rr=e=>{let t=e.log??[];for(let n=t.length-1;n>=0;n--){let r=t[n];if(r&&r.action==="close.issue"&&r.payload.id===e.id)return r.payload.parent}return null};var Ni=["00KM6CZ900T7180RM46K0JAYNF","00JR3R8E00A1Z4X9FGP9DV0SM5"],[Z,vt]=Ni;var w=(e,t)=>i(`${t.split(".").join(" ")+" failed, "+e.toLowerCase()}`),xi={"init.workspace":({action:e,payload:t})=>{let{id:n,name:r}=t,o=te.workspace(n,r);qt(o);let s=N.createNodeAtPosition(o);return a(s)?w(s.message??"Failed to initialize workspace",e):c("Workspace initialized",{action:e,result:s.data})},"add.workspace":({action:e,payload:t})=>{let{id:n,name:r}=t,o=te.workspace(n,r),s=N.createNodeAtPosition(o);return a(s)?w(s.message??"Failed to add workspace",e):c("Added workspace",{action:e,result:s.data})},"add.board":({action:e,payload:t})=>{let{id:n,name:r,parent:o}=t,s=N.createNodeAtPosition(te.board(n,r,o));return a(s)?w(s.message??"Unable to create board",e):c("Added board",{action:e,result:s.data})},"add.swimlane":({action:e,payload:t})=>{let{id:n,name:r,parent:o}=t,s=N.createNodeAtPosition(te.swimlane(n,r,o));return a(s)?w(s.message??"Unable to create swimlane",e):c("Added swimlane",{action:e,result:s.data})},"add.issue":({action:e,payload:t})=>{let{id:n,name:r,parent:o}=t,s=N.createNodeAtPosition(te.ticket(n,r,o));return a(s)?w(s.message??"Unable to create issue",e):c("Added issue",{action:e,result:s.data})},"add.field":({action:e,payload:t})=>{let{id:n,name:r,parent:o,val:s}=t,d=N.createNodeAtPosition(te.field(n,r,o,{value:s},r.includes("Description")?"vertical":"horizontal"));return a(d)?w(d.message??`Unable to create field: ${r}`,e):c("Added field",{action:e,result:d.data})},"edit.title":({action:e,payload:t})=>{let{id:n,name:r}=t;if(!N.getNode(n))return w("Unable to locate node",e);let s=N.renameNode(n,r);return a(s)?w(s.message??"Unable to edit title",e):c("Edited title",{action:e,result:s.data})},"delete.node":({action:e,payload:t})=>{let{id:n}=t,r=N.tombstoneNode(n);return a(r)?w(r.message??"Unable to delete node",e):c("Deleted node",{action:e,result:r.data})},"create.tag":({action:e,payload:t})=>{let{id:n,name:r}=t,o=N.createTag({id:n,name:r});return a(o)?w(o.message??"Unable to create tag",e):c("Tag added",{action:e,result:o.data})},"create.contributor":({action:e,payload:t})=>{let{id:n,name:r}=t,o=N.createContributor({id:n,name:r});return a(o)?w(o.message??"Unable to create contributor",e):c("Contributor created",{action:e,result:o.data})},"tag.issue":({action:e,payload:t})=>{let{id:n,target:r,tagId:o}=t,s=N.tag(r,o,n);return a(s)?w(s.message??"Unable to tag issue",e):c("Issue tagged",{action:e,result:s.data})},"assign.issue":({action:e,payload:t})=>{let{id:n,contributor:r,target:o}=t,s=N.assign(o,r,n);return a(s)?w(s.message??"Unable to assign issue",e):c("Assigned successfully",{action:e,result:s.data})},"move.node":({action:e,payload:t})=>{let{id:n,parent:r,pos:o}=t,s=N.moveNode({id:n,parentId:r,position:o});return a(s)?w(s.message??"Failed to move node",e):c("Moved node",{action:e,result:s.data})},"edit.description":({action:e,payload:t})=>{let{id:n,md:r}=t,o=N.editValue(n,r);return a(o)?w(o.message??"Unable to edit description",e):c("Set node value",{action:e,result:o.data})},"close.issue":({action:e,payload:t})=>{let{id:n}=t,r=N.getNode(n);if(!r)return w("Unable to locate issue",e);if(!J(r))return w("Can only close issues",e);let o=N.getNode(Z);if(!o)return w("Unable to locate target swimlane",e);if(o.id===r.parentNodeId)return w("Cannot close closed issue",e);let d=N.moveNode({id:n,parentId:o.id});return a(d)?w(d.message??"Unable to close issue",e):c("Issue closed",{action:e,result:d.data})},"reopen.issue":({action:e,payload:t})=>{let{id:n}=t,r=N.getNode(n);if(!r)return w("Unable to locate issue",e);if(!J(r))return w("Can only reopen issues",e);let o=N.getNode(Z);if(!o)return w("Unable to locate closed swimlane",e);if(!(r.parentNodeId===o.id))return w("Issue is not closed",e);let d=rr(r);if(!d)return w("Unable to resolve previous parent from issue history",e);if(d===o.id)return w("Previous parent resolves to closed swimlane",e);if(!N.getNode(d))return w("Previous parent no longer exists",e);let u=N.moveNode({id:n,parentId:d});return a(u)?w(u.message??"Unable to reopen issue",e):c("Issue reopened",{action:e,result:u.data})},"lock.node":({action:e,payload:t})=>{let{id:n}=t,r=N.lockNode(n);return a(r)?w(r.message??"Unable to lock node",e):c("Node locked",{action:e,result:r.data})}},Ii=(e,t)=>{let n=N.getNode(e);n&&N.updateNode({...n,log:[...n.log??[],t]})},Ci=e=>{switch(e.action){case"init.workspace":case"add.workspace":case"add.board":case"add.swimlane":case"add.issue":case"add.field":case"edit.title":case"lock.node":case"delete.node":case"move.node":case"close.issue":case"reopen.issue":return[e.payload.id];case"edit.description":let t=[e.payload.id],n=y().nodes[e.payload.id]?.parentNodeId;return n&&t.push(n),t;case"tag.issue":case"assign.issue":return[e.payload.id,e.payload.target];case"create.tag":case"create.contributor":default:return[]}};function he(e,t=!1){let n=xi[e.action](e);if(a(n))return n;t||([...new Set(Ci(e))].forEach(d=>Ii(d,e)),j(d=>({...d,eventLog:[...d.eventLog,e]})));let r=e.userId,o=e.userName;return!r?.length||!o?.length?w("Invalid user ID format",e.action):(N.createContributor({name:o,id:r}),n)}var Ee=e=>e.map(t=>he(t));function K(e){let t=he(e);if(t.result!==ee.Success)return t;let n=mt({event:e});return a(n)?n:t}function Re(e){return e.map(t=>K(t))}import Ke from"node:fs";import{spawn as Ri}from"node:child_process";import Jt from"node:fs";import Se from"node:path";var Be=(e,t)=>{let n=new Map,r=t??((...s)=>JSON.stringify(s)),o=((...s)=>{let d=r(...s);if(!n.has(d)){let l=e(...s).then(u=>(a(u)&&n.delete(d),u));n.set(d,l)}return n.get(d)});return o.clear=()=>n.clear(),o};import $e from"fs";import ir from"path";import bi from"util";var or=1e3,sr=(e=process.cwd())=>ir.join(ae(e),ne(),"log","epiq.log");function hi(e=process.cwd()){if(!ct)return;let t=sr(e);if(!$e.existsSync(t))return;let r=$e.readFileSync(t,"utf8").split(`
5
5
  `);if(r[r.length-1]===""&&r.pop(),r.length<=or)return;let o=r.slice(-or).join(`
6
6
  `)+`
7
- `;$e.writeFileSync(t,o,"utf8")}function qt(e,t,n=!1,r=process.cwd()){if(!at)return;let o=sr(r),s=bi.format(...t),d=new Date,u=`[${n?d.toISOString().slice(11,19):d.toISOString()}] ${e} ${s}
8
- `;$e.mkdirSync(ir.dirname(o),{recursive:!0}),$e.appendFileSync(o,u,"utf8"),hi(r)}var x={info(...e){qt("[Info]",e,!1)},debug(...e){qt("->",e,!0)},error(...e){qt("[Error]",[...e,new Error().stack],!1)}};globalThis.logger=x;var ar=15e3,Si={...process.env,GIT_TERMINAL_PROMPT:"0",GIT_ASKPASS:"echo"},cr=({args:e,cwd:t,allowFail:n})=>new Promise(r=>{if(!Gt.existsSync(t)){let v=`Git cwd does not exist: ${t}`;if(n){r({stdout:"",stderr:v,exitCode:1});return}r(i(v));return}let o=Ri("git",e,{cwd:t,stdio:["ignore","pipe","pipe"],env:Si}),s=!1,d="",l="",u=v=>{s||(s=!0,clearTimeout(f),r(v))},f=setTimeout(()=>{o.kill("SIGTERM");let v=[`git ${e.join(" ")}`,`cwd=${t}`,`Git command timed out after ${ar}ms`].join(`
9
- `);u(n?{stdout:d,stderr:v,exitCode:124}:i(v))},ar);o.stdout.setEncoding("utf8"),o.stderr.setEncoding("utf8"),o.stdout.on("data",v=>{d+=v}),o.stderr.on("data",v=>{l+=v}),o.on("error",v=>{if(n){u({stdout:d,stderr:v.message,exitCode:1});return}u(i([`git ${e.join(" ")}`,`cwd=${t}`,v.message].join(`
10
- `)))}),o.on("close",v=>{let E=v??1;if(n){u({stdout:d,stderr:l,exitCode:E});return}if(E!==0){u(i([`git ${e.join(" ")}`,l.trim()||d.trim()||"Git command failed"].filter(Boolean).join(`
11
- `)));return}u(c("Git command succeeded",{stdout:d,stderr:l,exitCode:E}))})}),T=({args:e,cwd:t})=>cr({args:e,cwd:t,allowFail:!1}),Ne=({args:e,cwd:t})=>cr({args:e,cwd:t,allowFail:!0}),lr=Be(async(e=process.cwd())=>{let t=await T({args:["rev-parse","--show-toplevel"],cwd:e});return a(t)?i("Not inside a Git repository"):c("Resolved repo root",t.data.stdout.trim())},e=>Se.resolve(e)),Ai=Be(async e=>{let t=await T({args:["rev-parse","--git-dir"],cwd:e});if(a(t))return i(t.message);let n=t.data.stdout.trim(),r=Se.isAbsolute(n)?n:Se.join(e,n);return c("Resolved git dir",r)},e=>Se.resolve(e)),Jt=async({cwd:e,message:t})=>{let n=await T({args:["commit","-m",t],cwd:e});if(a(n))return i(`Failed to create commit
7
+ `;$e.writeFileSync(t,o,"utf8")}function Gt(e,t,n=!1,r=process.cwd()){if(!ct)return;let o=sr(r),s=bi.format(...t),d=new Date,u=`[${n?d.toISOString().slice(11,19):d.toISOString()}] ${e} ${s}
8
+ `;$e.mkdirSync(ir.dirname(o),{recursive:!0}),$e.appendFileSync(o,u,"utf8"),hi(r)}var x={info(...e){Gt("[Info]",e,!1)},debug(...e){Gt("->",e,!0)},error(...e){Gt("[Error]",[...e,new Error().stack],!1)}};globalThis.logger=x;var ar=15e3,Si={...process.env,GIT_TERMINAL_PROMPT:"0",GIT_ASKPASS:"echo"},cr=({args:e,cwd:t,allowFail:n})=>new Promise(r=>{if(!Jt.existsSync(t)){let f=`Git cwd does not exist: ${t}`;if(n){r({stdout:"",stderr:f,exitCode:1});return}r(i(f));return}let o=Ri("git",e,{cwd:t,stdio:["ignore","pipe","pipe"],env:Si}),s=!1,d="",l="",u=f=>{s||(s=!0,clearTimeout(v),r(f))},v=setTimeout(()=>{o.kill("SIGTERM");let f=[`git ${e.join(" ")}`,`cwd=${t}`,`Git command timed out after ${ar}ms`].join(`
9
+ `);u(n?{stdout:d,stderr:f,exitCode:124}:i(f))},ar);o.stdout.setEncoding("utf8"),o.stderr.setEncoding("utf8"),o.stdout.on("data",f=>{d+=f}),o.stderr.on("data",f=>{l+=f}),o.on("error",f=>{if(n){u({stdout:d,stderr:f.message,exitCode:1});return}u(i([`git ${e.join(" ")}`,`cwd=${t}`,f.message].join(`
10
+ `)))}),o.on("close",f=>{let E=f??1;if(n){u({stdout:d,stderr:l,exitCode:E});return}if(E!==0){u(i([`git ${e.join(" ")}`,l.trim()||d.trim()||"Git command failed"].filter(Boolean).join(`
11
+ `)));return}u(c("Git command succeeded",{stdout:d,stderr:l,exitCode:E}))})}),T=({args:e,cwd:t})=>cr({args:e,cwd:t,allowFail:!1}),Ne=({args:e,cwd:t})=>cr({args:e,cwd:t,allowFail:!0}),lr=Be(async(e=process.cwd())=>{let t=await T({args:["rev-parse","--show-toplevel"],cwd:e});return a(t)?i("Not inside a Git repository"):c("Resolved repo root",t.data.stdout.trim())},e=>Se.resolve(e)),Ai=Be(async e=>{let t=await T({args:["rev-parse","--git-dir"],cwd:e});if(a(t))return i(t.message);let n=t.data.stdout.trim(),r=Se.isAbsolute(n)?n:Se.join(e,n);return c("Resolved git dir",r)},e=>Se.resolve(e)),Yt=async({cwd:e,message:t})=>{let n=await T({args:["commit","-m",t],cwd:e});if(a(n))return i(`Failed to create commit
12
12
  ${n.message}`);let r=await T({args:["rev-parse","HEAD"],cwd:e});return a(r)?i(`Commit created, but failed to read HEAD SHA
13
- ${r.message}`):c("Created commit and resolved SHA",r.data.stdout.trim())},Yt=async e=>{let t=await Ai(e);if(a(t))return i(t.message);let n=t.data,o=["MERGE_HEAD","CHERRY_PICK_HEAD","REVERT_HEAD","REBASE_HEAD","rebase-merge","rebase-apply"].filter(s=>Gt.existsSync(Se.join(n,s)));return c("Checked for in-progress Git operation",o.length>0)},ft=async({repoRoot:e,remote:t})=>{let n=await Ne({args:["remote","get-url",t],cwd:e});return c("Checked remote",n.exitCode===0)},vt=async({repoRoot:e,remote:t,branch:n})=>{let r=await Ne({args:["ls-remote","--heads",t,n],cwd:e});return r.exitCode!==0?i(r.stderr.trim()||`Unable to inspect remote branch ${t}/${n}`):c("Checked remote branch",r.stdout.trim().length>0)},ur=async({repoRoot:e,branch:t})=>{let n=await Ne({args:["show-ref","--verify","--quiet",`refs/heads/${t}`],cwd:e});return n.exitCode===0?c("Local branch exists",!0):n.exitCode===1?c("Local branch missing",!1):i(n.stderr.trim()||`Unable to inspect branch ${t}`)},dr=e=>{try{return Gt.realpathSync.native(e)}catch{return Se.resolve(e)}},mr=async({repoRoot:e,worktreeRoot:t})=>{let n=await T({args:["worktree","list","--porcelain"],cwd:e});if(a(n))return i(n.message);let r=dr(t),o=n.data.stdout.split(`
14
- `).filter(s=>s.startsWith("worktree ")).map(s=>s.slice(9)).map(dr).includes(r);return c("Checked worktree registration",o)},Xt=async e=>{let t=await Ne({args:["rev-parse","--abbrev-ref","--symbolic-full-name","@{u}"],cwd:e});return c("Checked upstream",t.exitCode===0&&t.stdout.trim().length>0)},yt=async e=>{let t=await T({args:["rev-parse","--abbrev-ref","HEAD"],cwd:e});return a(t)?i(t.message):c("Resolved current branch",t.data.stdout.trim())},pr=async e=>{let t=await T({args:["rev-parse","--short","HEAD"],cwd:e});return a(t)?i(t.message):c("Resolved short HEAD sha",t.data.stdout.trim())},gr=e=>e.includes("fetch first")||e.includes("non-fast-forward")||e.includes("failed to push some refs"),Qt=async({cwd:e,remote:t,branch:n})=>{let r=await vt({repoRoot:e,remote:t,branch:n});if(a(r))return i(r.message);if(!r.data)return c("Remote branch missing, skipped pull",!1);x.debug("[git] fetch start",{cwd:e,remote:t,branch:n});let o=await T({args:["fetch",t,n],cwd:e});if(x.debug("[git] fetch done",o),a(o))return i(`Failed to fetch ${n}
13
+ ${r.message}`):c("Created commit and resolved SHA",r.data.stdout.trim())},Xt=async e=>{let t=await Ai(e);if(a(t))return i(t.message);let n=t.data,o=["MERGE_HEAD","CHERRY_PICK_HEAD","REVERT_HEAD","REBASE_HEAD","rebase-merge","rebase-apply"].filter(s=>Jt.existsSync(Se.join(n,s)));return c("Checked for in-progress Git operation",o.length>0)},yt=async({repoRoot:e,remote:t})=>{let n=await Ne({args:["remote","get-url",t],cwd:e});return c("Checked remote",n.exitCode===0)},Et=async({repoRoot:e,remote:t,branch:n})=>{let r=await Ne({args:["ls-remote","--heads",t,n],cwd:e});return r.exitCode!==0?i(r.stderr.trim()||`Unable to inspect remote branch ${t}/${n}`):c("Checked remote branch",r.stdout.trim().length>0)},ur=async({repoRoot:e,branch:t})=>{let n=await Ne({args:["show-ref","--verify","--quiet",`refs/heads/${t}`],cwd:e});return n.exitCode===0?c("Local branch exists",!0):n.exitCode===1?c("Local branch missing",!1):i(n.stderr.trim()||`Unable to inspect branch ${t}`)},dr=e=>{try{return Jt.realpathSync.native(e)}catch{return Se.resolve(e)}},mr=async({repoRoot:e,worktreeRoot:t})=>{let n=await T({args:["worktree","list","--porcelain"],cwd:e});if(a(n))return i(n.message);let r=dr(t),o=n.data.stdout.split(`
14
+ `).filter(s=>s.startsWith("worktree ")).map(s=>s.slice(9)).map(dr).includes(r);return c("Checked worktree registration",o)},Zt=async e=>{let t=await Ne({args:["rev-parse","--abbrev-ref","--symbolic-full-name","@{u}"],cwd:e});return c("Checked upstream",t.exitCode===0&&t.stdout.trim().length>0)},Nt=async e=>{let t=await T({args:["rev-parse","--abbrev-ref","HEAD"],cwd:e});return a(t)?i(t.message):c("Resolved current branch",t.data.stdout.trim())},pr=async e=>{let t=await T({args:["rev-parse","--short","HEAD"],cwd:e});return a(t)?i(t.message):c("Resolved short HEAD sha",t.data.stdout.trim())},gr=e=>e.includes("fetch first")||e.includes("non-fast-forward")||e.includes("failed to push some refs"),Qt=async({cwd:e,remote:t,branch:n})=>{let r=await Et({repoRoot:e,remote:t,branch:n});if(a(r))return i(r.message);if(!r.data)return c("Remote branch missing, skipped pull",!1);x.debug("[git] fetch start",{cwd:e,remote:t,branch:n});let o=await T({args:["fetch",t,n],cwd:e});if(x.debug("[git] fetch done",o),a(o))return i(`Failed to fetch ${n}
15
15
  ${o.message}`);x.debug("[git] pull start",{cwd:e,remote:t,branch:n});let s=await T({args:["pull","--rebase",t,n],cwd:e});return x.debug("[git] pull done",s),a(s)?i(`Failed during pull --rebase
16
- ${s.message}`):c("Pulled with rebase",!0)},fr=async e=>{let t=await T({args:["status","--porcelain"],cwd:e});return a(t)?i(t.message):c("Checked remote worktree changes",t.data.stdout.trim().length>0)},vr=async e=>{let t=await yt(e);return a(t)?i(t.message):c("Checked detached HEAD state",t.data==="HEAD")};import{createHash as Di}from"node:crypto";import re from"node:fs";import Fi from"node:os";import $ from"node:path";import Et from"node:fs";import wi from"node:path";import{decodeTime as Ti}from"ulid";var Zt=e=>{let[t,n]=e.id;return`${t}:${n??""}`},yr=e=>{let[t]=e.id;return Ti(t)},Mi=e=>{let{userId:t,userName:n,...r}=e;return r},Li=e=>e.length===0?"":e.map(t=>JSON.stringify(Mi(t))).join(`
16
+ ${s.message}`):c("Pulled with rebase",!0)},fr=async e=>{let t=await T({args:["status","--porcelain"],cwd:e});return a(t)?i(t.message):c("Checked remote worktree changes",t.data.stdout.trim().length>0)},vr=async e=>{let t=await Nt(e);return a(t)?i(t.message):c("Checked detached HEAD state",t.data==="HEAD")};import{createHash as Di}from"node:crypto";import re from"node:fs";import Fi from"node:os";import $ from"node:path";import xt from"node:fs";import wi from"node:path";import{decodeTime as Ti}from"ulid";var en=e=>{let[t,n]=e.id;return`${t}:${n??""}`},yr=e=>{let[t]=e.id;return Ti(t)},Mi=e=>{let{userId:t,userName:n,...r}=e;return r},Li=e=>e.length===0?"":e.map(t=>JSON.stringify(Mi(t))).join(`
17
17
  `)+`
18
- `,Pi=(e,t)=>{let n=new Map;for(let r of[...t,...e])n.set(Zt(r),r);return[...n.values()].sort((r,o)=>{let s=yr(r)-yr(o);return s!==0?s:Zt(r).localeCompare(Zt(o))})},Nt=({sourceFile:e,targetFile:t})=>{let n=pt(e);if(a(n))return i(n.message);let r=pt(t);if(a(r))return i(r.message);let o=Pi(r.data,n.data),s=Li(o);return(Et.existsSync(t)?Et.readFileSync(t,"utf8"):"")===s?c("Event file already merged",!1):(Et.mkdirSync(wi.dirname(t),{recursive:!0}),Et.writeFileSync(t,s,"utf8"),c("Merged event file",!0))};var L="epiq/events",B="origin",en=ne(),Nr="events",ki="4b825dc642cb6eb9a060e54bf8d69288fbee4904",Oi=e=>$.join(en,Nr,e),Ui=e=>Di("sha1").update($.resolve(e)).digest("hex").slice(0,12),xr=()=>$.join(Fi.homedir(),".epiq"),Ir=()=>$.join(xr(),"worktrees"),Cr=e=>$.join(Ir(),Ui(e)),_i=e=>$.join(e,en),Ae=e=>$.join(_i(e),Nr),He=({root:e,fileName:t})=>$.join(Ae(e),t),xt=e=>(x.debug("[sync] ensure dir",e),re.mkdirSync(e,{recursive:!0}),c("Ensured directory",void 0)),Wi=()=>{x.debug("[sync] ensure epiq storage");let e=xt(xr());if(a(e))return i(e.message);let t=xt(Ir());return a(t)?i(t.message):c("Ensured epiq storage",void 0)},Bi=e=>{re.existsSync(e)&&(x.debug("[sync] remove path",e),re.rmSync(e,{recursive:!0,force:!0}))},$i=e=>{let t=Ae(e);if(!re.existsSync(t))return x.debug("[sync] events dir missing",t),c("Events dir missing",[]);let n=re.readdirSync(t,{withFileTypes:!0}).filter(r=>r.isFile()).map(r=>r.name).filter(r=>r.endsWith(".jsonl")).sort();return x.debug("[sync] listed event files",{eventsDir:t,count:n.length}),c("Listed event files",n)},Hi=async e=>{x.debug("[sync] inspect local HEAD",e);let t=await Ne({args:["rev-parse","--verify","HEAD"],cwd:e});return t.exitCode===0?c("Repo has HEAD",!0):t.exitCode===1?c("Repo has no HEAD",!1):i(t.stderr.trim()||"Unable to inspect HEAD")},Ki=Be(async e=>{x.debug("[sync] inspect remote history",{repoRoot:e,remote:B});let t=await ft({repoRoot:e,remote:B});if(a(t))return i(t.message);if(!t.data)return c("No remote configured",!1);let n=await Ne({args:["ls-remote","--heads",B],cwd:e});if(n.exitCode!==0)return i(n.stderr.trim()||"Unable to inspect remote heads");let r=n.stdout.trim().length>0;return x.debug("[sync] remote history",r),c("Checked remote history",r)},e=>$.resolve(e)),br=async e=>{x.debug("[sync] ensure initial commit");let t=await Hi(e);if(a(t))return i(t.message);if(t.data)return x.debug("[sync] local HEAD exists"),c("Repo already initialized",!1);let n=await Ki(e);if(a(n))return i(n.message);if(n.data)return x.debug("[sync] skip local init commit due to remote history"),c("Skipped local init commit because remote history exists",!1);x.debug("[sync] create empty init commit");let r=await T({args:["commit","--allow-empty","-m","[epiq:init]"],cwd:e});return a(r)?i(`Failed to create initial commit
19
- ${r.message}`):c("Created initial commit",!0)},hr=({repoRoot:e,worktreeRoot:t})=>{let n=$i(t);if(a(n))return i(n.message);let r=Ae(t),o=Ae(e),s=!1;for(let d of n.data){let l=$.join(r,d),u=$.join(o,d);x.debug("[sync] hydrate event file",{from:l,to:u});let f=Nt({sourceFile:l,targetFile:u});if(a(f))return i(f.message);s=s||f.data}return x.debug("[sync] hydrate changed",s),c("Hydrated event files from remote worktree",s)},Er=e=>e.trim().replace(/\s+/g,"-").replace(/[^A-Za-z0-9._/-]/g,"-").replace(/-+/g,"-").replace(/^[-/.]+|[-/.]+$/g,"")||"unknown",Vi=async e=>{let t=await yt(e);if(a(t))return i(t.message);let n=await pr(e);if(a(n))return i(n.message);let r=`[epiq:sync:${Er(t.data)}:${Er(n.data)}]`;return x.debug("[sync] commit message",r),c("Built sync commit message",r)},ji=async e=>{x.debug("[sync] create empty storage branch",L);let t=await T({args:["commit-tree",ki,"-m","[epiq:init-storage-branch]"],cwd:e});if(a(t))return i(`Failed to create storage branch commit
18
+ `,Pi=(e,t)=>{let n=new Map;for(let r of[...t,...e])n.set(en(r),r);return[...n.values()].sort((r,o)=>{let s=yr(r)-yr(o);return s!==0?s:en(r).localeCompare(en(o))})},It=({sourceFile:e,targetFile:t})=>{let n=ft(e);if(a(n))return i(n.message);let r=ft(t);if(a(r))return i(r.message);let o=Pi(r.data,n.data),s=Li(o);return(xt.existsSync(t)?xt.readFileSync(t,"utf8"):"")===s?c("Event file already merged",!1):(xt.mkdirSync(wi.dirname(t),{recursive:!0}),xt.writeFileSync(t,s,"utf8"),c("Merged event file",!0))};var L="epiq/events",B="origin",tn=ne(),Nr="events",ki="4b825dc642cb6eb9a060e54bf8d69288fbee4904",Oi=e=>$.join(tn,Nr,e),Ui=e=>Di("sha1").update($.resolve(e)).digest("hex").slice(0,12),xr=()=>$.join(Fi.homedir(),".epiq"),Ir=()=>$.join(xr(),"worktrees"),Cr=e=>$.join(Ir(),Ui(e)),_i=e=>$.join(e,tn),Ae=e=>$.join(_i(e),Nr),He=({root:e,fileName:t})=>$.join(Ae(e),t),Ct=e=>(x.debug("[sync] ensure dir",e),re.mkdirSync(e,{recursive:!0}),c("Ensured directory",void 0)),Wi=()=>{x.debug("[sync] ensure epiq storage");let e=Ct(xr());if(a(e))return i(e.message);let t=Ct(Ir());return a(t)?i(t.message):c("Ensured epiq storage",void 0)},Bi=e=>{re.existsSync(e)&&(x.debug("[sync] remove path",e),re.rmSync(e,{recursive:!0,force:!0}))},$i=e=>{let t=Ae(e);if(!re.existsSync(t))return x.debug("[sync] events dir missing",t),c("Events dir missing",[]);let n=re.readdirSync(t,{withFileTypes:!0}).filter(r=>r.isFile()).map(r=>r.name).filter(r=>r.endsWith(".jsonl")).sort();return x.debug("[sync] listed event files",{eventsDir:t,count:n.length}),c("Listed event files",n)},Hi=async e=>{x.debug("[sync] inspect local HEAD",e);let t=await Ne({args:["rev-parse","--verify","HEAD"],cwd:e});return t.exitCode===0?c("Repo has HEAD",!0):t.exitCode===1?c("Repo has no HEAD",!1):i(t.stderr.trim()||"Unable to inspect HEAD")},Ki=Be(async e=>{x.debug("[sync] inspect remote history",{repoRoot:e,remote:B});let t=await yt({repoRoot:e,remote:B});if(a(t))return i(t.message);if(!t.data)return c("No remote configured",!1);let n=await Ne({args:["ls-remote","--heads",B],cwd:e});if(n.exitCode!==0)return i(n.stderr.trim()||"Unable to inspect remote heads");let r=n.stdout.trim().length>0;return x.debug("[sync] remote history",r),c("Checked remote history",r)},e=>$.resolve(e)),br=async e=>{x.debug("[sync] ensure initial commit");let t=await Hi(e);if(a(t))return i(t.message);if(t.data)return x.debug("[sync] local HEAD exists"),c("Repo already initialized",!1);let n=await Ki(e);if(a(n))return i(n.message);if(n.data)return x.debug("[sync] skip local init commit due to remote history"),c("Skipped local init commit because remote history exists",!1);x.debug("[sync] create empty init commit");let r=await T({args:["commit","--allow-empty","-m","[epiq:init]"],cwd:e});return a(r)?i(`Failed to create initial commit
19
+ ${r.message}`):c("Created initial commit",!0)},hr=({repoRoot:e,worktreeRoot:t})=>{let n=$i(t);if(a(n))return i(n.message);let r=Ae(t),o=Ae(e),s=!1;for(let d of n.data){let l=$.join(r,d),u=$.join(o,d);x.debug("[sync] hydrate event file",{from:l,to:u});let v=It({sourceFile:l,targetFile:u});if(a(v))return i(v.message);s=s||v.data}return x.debug("[sync] hydrate changed",s),c("Hydrated event files from remote worktree",s)},Er=e=>e.trim().replace(/\s+/g,"-").replace(/[^A-Za-z0-9._/-]/g,"-").replace(/-+/g,"-").replace(/^[-/.]+|[-/.]+$/g,"")||"unknown",Vi=async e=>{let t=await Nt(e);if(a(t))return i(t.message);let n=await pr(e);if(a(n))return i(n.message);let r=`[epiq:sync:${Er(t.data)}:${Er(n.data)}]`;return x.debug("[sync] commit message",r),c("Built sync commit message",r)},ji=async e=>{x.debug("[sync] create empty storage branch",L);let t=await T({args:["commit-tree",ki,"-m","[epiq:init-storage-branch]"],cwd:e});if(a(t))return i(`Failed to create storage branch commit
20
20
  ${t.message}`);let n=t.data.stdout.trim(),r=await T({args:["update-ref",`refs/heads/${L}`,n],cwd:e});return a(r)?i(`Failed to create ${L}
21
- ${r.message}`):c("Created empty storage branch",!0)},zi=async({repoRoot:e})=>{x.debug("[sync] ensure local remote branch",L);let t=await ur({repoRoot:e,branch:L});if(a(t))return i(t.message);if(t.data)return x.debug("[sync] local remote branch exists"),c("Local remote branch already exists",!1);let n=await ft({repoRoot:e,remote:B});if(a(n))return i(n.message);if(n.data){let r=await vt({repoRoot:e,remote:B,branch:L});if(a(r))return i(r.message);if(r.data){x.debug("[sync] fetch remote branch before local track");let o=await T({args:["fetch",B,L],cwd:e});if(a(o))return i(`Failed to fetch ${L} from remote
21
+ ${r.message}`):c("Created empty storage branch",!0)},zi=async({repoRoot:e})=>{x.debug("[sync] ensure local remote branch",L);let t=await ur({repoRoot:e,branch:L});if(a(t))return i(t.message);if(t.data)return x.debug("[sync] local remote branch exists"),c("Local remote branch already exists",!1);let n=await yt({repoRoot:e,remote:B});if(a(n))return i(n.message);if(n.data){let r=await Et({repoRoot:e,remote:B,branch:L});if(a(r))return i(r.message);if(r.data){x.debug("[sync] fetch remote branch before local track");let o=await T({args:["fetch",B,L],cwd:e});if(a(o))return i(`Failed to fetch ${L} from remote
22
22
  ${o.message}`);x.debug("[sync] create local tracking branch",L);let s=await T({args:["branch","--track",L,`${B}/${L}`],cwd:e});return a(s)?i(`Failed to create local ${L} from remote
23
23
  ${s.message}`):c("Created local remote branch from remote",!0)}}return ji(e)},qi=async({repoRoot:e,branch:t})=>{let n=await T({args:["worktree","list","--porcelain"],cwd:e});if(a(n))return i(n.message);let r=n.data.stdout.split(`
24
- `),o=null;for(let s of r){if(s.startsWith("worktree ")){o=s.slice(9);continue}if(s===`branch refs/heads/${t}`&&o)return c("Found worktree for branch",o)}return c("No worktree found for branch",null)},Gi=async({repoRoot:e,worktreeRoot:t})=>{x.debug("[sync] create remote worktree",t);let n=xt($.dirname(t));if(a(n))return i(n.message);re.existsSync(t)&&!re.existsSync($.join(t,".git"))&&(x.debug("[sync] remove broken remote worktree path",t),Bi(t));let r=await T({args:["worktree","add",t,L],cwd:e});return a(r)?i(`Failed to create remote worktree
24
+ `),o=null;for(let s of r){if(s.startsWith("worktree ")){o=s.slice(9);continue}if(s===`branch refs/heads/${t}`&&o)return c("Found worktree for branch",o)}return c("No worktree found for branch",null)},Gi=async({repoRoot:e,worktreeRoot:t})=>{x.debug("[sync] create remote worktree",t);let n=Ct($.dirname(t));if(a(n))return i(n.message);re.existsSync(t)&&!re.existsSync($.join(t,".git"))&&(x.debug("[sync] remove broken remote worktree path",t),Bi(t));let r=await T({args:["worktree","add",t,L],cwd:e});return a(r)?i(`Failed to create remote worktree
25
25
  ${r.message}`):c("Created remote worktree",!0)},Ji=async({repoRoot:e,worktreeRoot:t})=>{x.debug("[sync] ensure remote worktree",t);let n=await qi({repoRoot:e,branch:L});if(a(n))return i(n.message);let r=n.data,o=$.resolve(t),s=r?$.resolve(r):null;if(s&&s===o&&re.existsSync(s))return x.debug("[sync] reuse existing remote branch worktree",{expected:o,actual:s}),c("Remote branch already checked out in expected worktree",!1);if(s&&s!==o){x.debug("[sync] remove old remote branch worktree",{expected:o,actual:s});let u=await T({args:["worktree","remove","--force",s],cwd:e});if(a(u))return i(`Failed to remove existing remote worktree
26
26
  ${u.message}`)}if(s&&!re.existsSync(s)){x.debug("[sync] prune stale branch worktree registration",{existingBranchWorktree:s});let u=await T({args:["worktree","prune"],cwd:e});if(a(u))return i(`Failed to prune stale worktrees
27
27
  ${u.message}`)}let d=await mr({repoRoot:e,worktreeRoot:t});if(a(d))return i(d.message);let l=re.existsSync(t);if(d.data&&l)return x.debug("[sync] remote worktree exists"),c("Remote worktree already exists",!1);if(d.data&&!l){x.debug("[sync] prune stale remote worktree registration");let u=await T({args:["worktree","prune"],cwd:e});if(a(u))return i(`Failed to prune stale worktrees
28
- ${u.message}`)}return Gi({repoRoot:e,worktreeRoot:t})},Yi=async e=>{let t=await yt(e);if(a(t))return i(t.message);if(t.data===L)return x.debug("[sync] remote branch already checked out"),c("Remote branch already checked out",!1);x.debug("[sync] checkout remote branch",L);let n=await T({args:["checkout",L],cwd:e});return a(n)?i(`Failed to checkout ${L}
28
+ ${u.message}`)}return Gi({repoRoot:e,worktreeRoot:t})},Yi=async e=>{let t=await Nt(e);if(a(t))return i(t.message);if(t.data===L)return x.debug("[sync] remote branch already checked out"),c("Remote branch already checked out",!1);x.debug("[sync] checkout remote branch",L);let n=await T({args:["checkout",L],cwd:e});return a(n)?i(`Failed to checkout ${L}
29
29
  ${n.message}`):c("Checked out remote branch",!0)},Xi=async e=>{let t=await T({args:["ls-tree","--name-only","HEAD"],cwd:e});if(a(t))return i(t.message);let r=t.data.stdout.trim().split(`
30
- `).filter(Boolean).filter(d=>d!==en);if(r.length===0)return c("Remote branch is storage-only",!1);x.debug("[sync] remove app files from storage branch",r);let o=await T({args:["rm","-r","--ignore-unmatch","--",...r],cwd:e});if(a(o))return i(`Failed to clean storage branch
31
- ${o.message}`);let s=await Jt({cwd:e,message:"[epiq:repair-storage-branch]"});return a(s)?i(s.message):c("Cleaned storage branch",!0)},Qi=async e=>{x.debug("[sync] ensure remote upstream",L);let t=await Xt(e);if(a(t))return i(t.message);if(t.data)return x.debug("[sync] remote upstream already configured"),c("Remote upstream already configured",!1);let n=await ft({repoRoot:e,remote:B});if(a(n))return i(n.message);if(!n.data)return x.debug("[sync] no remote configured for upstream"),c("No remote available for upstream",!1);let r=await vt({repoRoot:e,remote:B,branch:L});if(a(r))return i(r.message);if(!r.data)return x.debug("[sync] remote branch missing; upstream will be configured on first push"),c("Deferred upstream until first push",!1);x.debug("[sync] fetch remote branch before upstream set");let o=await T({args:["fetch",B,L],cwd:e});if(a(o))return i(`Failed to fetch ${L}
30
+ `).filter(Boolean).filter(d=>d!==tn);if(r.length===0)return c("Remote branch is storage-only",!1);x.debug("[sync] remove app files from storage branch",r);let o=await T({args:["rm","-r","--ignore-unmatch","--",...r],cwd:e});if(a(o))return i(`Failed to clean storage branch
31
+ ${o.message}`);let s=await Yt({cwd:e,message:"[epiq:repair-storage-branch]"});return a(s)?i(s.message):c("Cleaned storage branch",!0)},Zi=async e=>{x.debug("[sync] ensure remote upstream",L);let t=await Zt(e);if(a(t))return i(t.message);if(t.data)return x.debug("[sync] remote upstream already configured"),c("Remote upstream already configured",!1);let n=await yt({repoRoot:e,remote:B});if(a(n))return i(n.message);if(!n.data)return x.debug("[sync] no remote configured for upstream"),c("No remote available for upstream",!1);let r=await Et({repoRoot:e,remote:B,branch:L});if(a(r))return i(r.message);if(!r.data)return x.debug("[sync] remote branch missing; upstream will be configured on first push"),c("Deferred upstream until first push",!1);x.debug("[sync] fetch remote branch before upstream set");let o=await T({args:["fetch",B,L],cwd:e});if(a(o))return i(`Failed to fetch ${L}
32
32
  ${o.message}`);x.debug("[sync] set upstream to remote branch");let s=await T({args:["branch","--set-upstream-to",`${B}/${L}`,L],cwd:e});return a(s)?i(`Failed to set remote upstream
33
33
  ${s.message}`):c("Configured remote upstream",!0)},Rr=async({worktreeRoot:e,ownEventFileName:t})=>{x.debug("[sync] stage own event file in remote worktree",t);let n=await T({args:["add",Oi(t)],cwd:e});return a(n)?i(`Failed to stage remote own event file
34
- ${n.message}`):c("Staged remote own event file",void 0)},Sr=async({repoRoot:e,worktreeRoot:t})=>{let n=await Vi(e);return a(n)?i(n.message):(x.debug("[sync] create remote sync commit"),Jt({cwd:t,message:n.data}))},tn=async e=>{x.debug("[sync] push remote worktree");let t=await Xt(e);if(a(t))return i(t.message);let n=await T({args:t.data?["push"]:["push","-u",B,L],cwd:e});return x.debug("[sync] push result",n),a(n)?i(`Failed during remote push
35
- ${n.message}`):c("Pushed remote",!0)},Ar=async({repoRoot:e,worktreeRoot:t,ensureUpstream:n})=>{x.debug("[sync] bootstrap remote storage",{repoRoot:e,worktreeRoot:t,ensureUpstream:n});let r=!1,o=[Wi(),await zi({repoRoot:e}),await Ji({repoRoot:e,worktreeRoot:t}),await Yi(t),await Xi(t),n?await Qi(t):c("Skipped remote upstream bootstrap",!1)];for(let s of o){if(a(s))return i(s.message);r=r||!!s.data}return x.debug("[sync] bootstrap changed",r),c(n?"Bootstrapped remote storage":"Bootstrapped remote storage (readonly)",r)},wr=(e,t)=>{for(let n of[Ae(e),Ae(t)]){let r=xt(n);if(a(r))return i(r.message)}return c("Ensured remote layout",void 0)};var Zi=({repoRoot:e,worktreeRoot:t,ownEventFileName:n})=>{let r=He({root:e,fileName:n}),o=He({root:t,fileName:n});return Ke.existsSync(r)?(logger.debug("[sync] merge own event file to remote",{ownEventFileName:n,localFile:r,remoteFile:o}),Nt({sourceFile:r,targetFile:o})):(logger.debug("[sync] local own event file missing",r),c("Local own event file missing, nothing to merge",!1))},Tr=async({repoRoot:e,worktreeRoot:t,ownEventFileName:n})=>{let r=Zi({repoRoot:e,worktreeRoot:t,ownEventFileName:n});if(a(r))return i(r.message);let o=await fr(t);if(a(o))return i(o.message);if(!r.data&&!o.data)return c("Own event file already up to date in remote worktree",{createdCommit:!1});let s=await Rr({worktreeRoot:t,ownEventFileName:n});if(a(s))return i(s.message);let d=await Sr({repoRoot:e,worktreeRoot:t});return a(d)?i(d.message):c("Merged, staged, and committed own event file",{createdCommit:!0,commitSha:d.data})},Mr=({repoRoot:e,worktreeRoot:t,ownEventFileName:n})=>{let r=He({root:e,fileName:n}),o=He({root:t,fileName:n});logger.debug("[sync] own event file sizes",{local:Ke.existsSync(r)?Ke.statSync(r).size:0,remote:Ke.existsSync(o)?Ke.statSync(o).size:0})},It=async({cwd:e=process.cwd(),ownEventFileName:t})=>{logger.debug("[sync] start write sync",{cwd:e,ownEventFileName:t});let n=await lr(e);if(a(n))return i(n.message);let r=n.data,o=Cr(r);logger.debug("[sync] resolved roots",{repoRoot:r,worktreeRoot:o});let s=await vr(r);if(a(s))return i(s.message);if(s.data)return i("Cannot run :sync while the repository is in detached HEAD state");if(t.includes("/")||t.includes("\\"))return i("Own event file must be a file name, not a path");if(!t.endsWith(".jsonl"))return i("Own event file must end with .jsonl");let d=await Yt(r);if(a(d))return i(d.message);if(d.data)return i("Cannot run :sync while a merge, rebase, cherry-pick, or revert is in progress in the current repo");let l=await br(r);if(a(l))return i(l.message);logger.debug("[sync] ensure initial commit changed",l.data);let u=await Ar({repoRoot:r,worktreeRoot:o,ensureUpstream:!0});if(a(u))return i(u.message);let f=await Yt(o);if(a(f))return i(f.message);if(f.data)return i("Cannot run :sync while a merge, rebase, cherry-pick, or revert is in progress in the remote worktree");let v=wr(r,o);if(a(v))return i(v.message);let E=!1,C,R=!1,M=!1,Q=!1;logger.debug("[sync] pull remote branch before local copy");let Tt=await Qt({cwd:o,remote:B,branch:L});if(a(Tt))return i(Tt.message);R=Tt.data,logger.debug("[sync] pulled remote",R);let Mt=hr({repoRoot:r,worktreeRoot:o});if(a(Mt))return i(Mt.message);Q=Mt.data,logger.debug("[sync] hydrated from remote",Q);let Le=await Tr({repoRoot:r,worktreeRoot:o,ownEventFileName:t});if(a(Le))return i(Le.message);if(E=Le.data.createdCommit,C=Le.data.commitSha,Mr({repoRoot:r,worktreeRoot:o,ownEventFileName:t}),logger.debug("[sync] sync own file result",Le.data),E||u.data){let fe=await tn(o),je=fe;if(a(fe)&&gr(fe.message)){let mn=await Qt({cwd:o,remote:B,branch:L});if(a(mn))return i(mn.message);let Pe=await Tr({repoRoot:r,worktreeRoot:o,ownEventFileName:t});if(a(Pe))return i(Pe.message);Pe.data.createdCommit&&(E=!0,C=Pe.data.commitSha),Mr({repoRoot:r,worktreeRoot:o,ownEventFileName:t}),logger.debug("[sync] retry sync own file result",Pe.data),je=await tn(o)}if(a(je))return i(je.message);M=je.data,logger.debug("[sync] pushed remote",M)}else logger.debug("[sync] no commit created, skipped push");if(E){let fe=await T({args:["rev-parse","HEAD"],cwd:o});if(a(fe))return i(fe.message);C=fe.data.stdout.trim()}return c("Synced event logs with remote",{repoRoot:r,worktreeRoot:o,createdCommit:E,commitSha:C,pulled:R,pushed:M,hydrated:Q,bootstrapped:u.data})};import{ulid as Lr}from"ulid";var we=null,pe=()=>structuredClone(we),Te=e=>we=e,Pr=()=>{let{currentNode:e,selectedIndex:t}=y(),r=A(e.id)[t];return r?c("Resolved selected child",r):i("Target node not found")};function nn(e){let t=Pr();if(a(t))return t;let{currentNode:n,nodes:r}=y();if(!n.parentNodeId)return i("Missing parent node id");let o=r[n.parentNodeId];if(!o)return i("Missing parent node");let s=V(o.id),d=s.findIndex(({id:C})=>C===n.id);if(d<0)return i("Current node not found among siblings");let l=s[d+e];if(!l)return i("Missing sibling node");let u=H();if(a(u))return i("Unable to resolve user ID");let{userId:f,userName:v}=u.data;if(Te({id:Lr(),userId:f,userName:v,action:"move.node",payload:{id:t.data.id,parent:l.id,pos:{at:"end"}}}),!we)return i("Could not materialize move state");let E=he(we,!0);return a(E)?E:c("Node moved successfully",E.data)}function rn(e){let t=Pr();if(a(t))return t;let{currentNode:n,selectedIndex:r}=y(),s=V(n.id)[r+e];if(!s)return i("Missing sibling node");let d=H();if(a(d))return i("Unable to resolve user ID");let{userId:l,userName:u}=d.data;if(Te({id:Lr(),userId:l,userName:u,action:"move.node",payload:{id:t.data.id,parent:n.id,pos:{at:e===1?"after":"before",sibling:s.id}}}),!we)return i("Could not materialize move state");let f=he(we,!0);return a(f)?f:c("Node moved successfully",f.data)}import es from"node:os";import Dr from"node:path";import{z as Ct}from"zod";var ts={userId:"",userName:"",preferredEditor:""},Fr=Ct.object({preferredEditor:Ct.string().optional(),userName:Ct.string().optional(),userId:Ct.string().optional()}).strict(),ns=".epiq",rs="config.json",kr=()=>Dr.join(es.homedir(),ns),on=()=>Dr.join(kr(),rs),sn=()=>{try{return q.mkDir(kr()),c("Ensured ~/.epiq exists",null)}catch{return i("Unable to create ~/.epiq")}},os=e=>{let t;try{t=JSON.parse(e)}catch{return i("Invalid ~/.epiq/config.json JSON")}let n=Fr.safeParse(t??{});return n.success?c("Parsed config",n.data):i(`Invalid ~/.epiq/config.json shape: ${n.error.issues.map(r=>r.path.join(".")||r.message).join(", ")}`)},Or=()=>{let e=sn();if(a(e))return i(e.message);let t=on(),n=q.readFile(t);return n==null||n.trim()===""?c("No config found, using empty config",{}):os(n)},Ur=e=>{let t=sn();if(a(t))return i(t.message);let n=Fr.safeParse(e);if(!n.success)return i(`Invalid config: ${n.error.issues.map(o=>o.path.join(".")||o.message).join(", ")}`);let r=on();try{return q.writeToFile(r,JSON.stringify(n.data,null,2)+`
36
- `),c("Config written",null)}catch{return i("Unable to write ~/.epiq/config.json")}},an=e=>{let t=Or();if(a(t))return i("Failed to read existing config");let n={...t.data,...e};return Ur(n)},_r=()=>{let e=on(),t=sn();if(a(t))return i("Unable to create ~/.epiq");if(!(q.readFile(e)!==null)){let l=Ur(ts);if(a(l))throw new Error("Unable to create ~/.epiq/config.json")}let r=Or();if(a(r))throw new Error(r.message||"Unable to load settings");let{preferredEditor:o,userName:s,userId:d}=r.data;return!s||!d?i("User name or ID not configured in ~/.epiq/config.json"):c("successfully loaded settings",{preferredEditor:o??"",userName:s,userId:d})};var is=e=>Object.values(y().tags).find(t=>t.name===e),ss=e=>Object.values(y().contributors).find(t=>t.name===e),Wr=[{systemOnly:!0,intent:b.Move,mode:p.COMMAND_LINE,action:()=>{let e=H();if(a(e))return i("Unable to resolve user ID");let{modifier:t}=te().commandMeta,n=()=>{let l=pe();if(!l)return i("No pending move state");let u=l.payload.id;if(!y().nodes[u])return i("Moved node not found");let v=l.payload.parent,E=y().nodes[v];if(!E)return i("Move parent not found");let C=A(v).findIndex(R=>R.id===u);return C===-1?i("Moved node not found among rendered children"):(O.navigate({currentNode:E,selectedIndex:C}),c("Synchronized navigation to moved node",null))},r=l=>{if(a(l))return i(l.message);let u=n();return a(u)?i(u.message):c("Updated move preview",null)},{currentNode:o,selectedIndex:s}=y(),d=A(o.id)[s];if(!d)return I({mode:p.DEFAULT}),i("No move target");if(t==="start"){if(d.readonly)return i("Target node is read-only");if(s===-1)return i("No item selected");if(!d.parentNodeId)return i("Target has no parent");let l=A(d.parentNodeId),u=l.findIndex(({id:R})=>R===d.id);if(u===-1)return i("Target not found among siblings");let f=l[u-1],v=l[u+1],E=v!=null?{at:"before",sibling:v.id}:f!=null?{at:"after",sibling:f.id}:{at:"start"};Te({id:F(),action:"move.node",payload:{id:d.id,parent:d.parentNodeId,pos:E},...e.data}),I({mode:p.MOVE});let C=n();return a(C)?i(C.message):c("Move initialized",null)}if(t==="next")return I({mode:p.MOVE}),r(rn(1));if(t==="previous")return I({mode:p.MOVE}),r(rn(-1));if(t==="to-next")return I({mode:p.MOVE}),r(nn(1));if(t==="to-previous")return I({mode:p.MOVE}),r(nn(-1));if(t==="confirm"){I({mode:p.DEFAULT});let l=pe();if(!l)return i("No pending move to confirm");let u=K(l);if(a(u))return u;let f=n();return a(f)?i(f.message):(Te(null),c("Moved item",null))}return t==="cancel"?(Te(null),I({mode:p.DEFAULT}),c("Cancelling move",null)):i("Invalid move modifier")}},{intent:b.Delete,mode:p.COMMAND_LINE,action:()=>{let e=H();if(a(e))return i("Unable to resolve user ID");let{currentNode:t,selectedIndex:n}=y(),r=A(t.id)[n];return r?K({id:F(),action:"delete.node",payload:{id:r.id},...e.data}):i("Unable to resolve child to delete")},onSuccess:()=>I({mode:p.DEFAULT})},{intent:b.Edit,mode:p.COMMAND_LINE,action:()=>{let e=H();if(a(e))return i("Unable to resolve user ID");let t=ve(y().breadCrumb,"TICKET");if(a(t))return i("Edit target must be an issue");let n=t.data;if(n.readonly)return i("Cannot edit readonly field");let{currentNode:r,selectedIndex:o}=y();if(!A(n.id)[o])return i("No selected field");let d=A(r.id)[o];if(!d)return i("No selected field");if(d.readonly)return i("Cannot edit readonly field");let l=d.props.value;if(typeof l!="string")return i("Selected field is not editable text");let u=Jn(l);if(a(u))return i("Failed to edit field");let f=u.data;return f===l?c("No changes made",null):d.title==="Description"?K({id:F(),action:"edit.description",payload:{id:d.id,md:f},...e.data}):d.title==="Title"?K({id:F(),action:"edit.title",payload:{id:d.id,name:f},...e.data}):i(`Editing not supported for "${d.title}"`)},onSuccess:()=>I({mode:p.DEFAULT})},{intent:b.Filter,mode:p.COMMAND_LINE,action:()=>{let{modifier:e,inputString:t}=te().commandMeta,n=/(!=|=)/,[r,o]=e.split(n);if(!r||!(l=>_(m.FILTER).map(u=>u.split(n)[0]).includes(l))(r))return i("Invalid filter modifier");let d={target:r,operator:"=",value:t.trim()};return j(l=>({...l,filters:e==="clear"?[]:[...l.filters,d],mode:p.DEFAULT})),c("Viewing help",null)}},{intent:b.ViewHelp,mode:p.COMMAND_LINE,action:()=>(I({mode:p.HELP}),c("Viewing help",null))},{intent:b.CloseIssue,mode:p.COMMAND_LINE,action:()=>{let e=H();if(a(e))return i("Unable to resolve user ID");let{currentNode:t,selectedIndex:n}=y(),r=A(t.id)[n];if(!r)return i("Unable to close issue, no target found");if(!r.parentNodeId)return i("No target parent found");if(!J(r))return i("Cannot close in this context");let o=K({id:F(),action:"close.issue",payload:{id:r.id,parent:r.parentNodeId},...e.data});return a(o)?o:c("Viewing help",null)}},{intent:b.ReopenIssue,mode:p.COMMAND_LINE,action:()=>{let e=H();if(a(e))return i("Unable to resolve user ID");let{currentNode:t,selectedIndex:n}=y(),r=A(t.id)[n];if(!r)return i("Unable to reopen issue, no target found");let o=r.context==="TICKET"?c("Resolved ticket",r):Ye(r.id,"TICKET");if(a(o))return i("Cannot reopen in this context");let s=o.data,d=K({id:F(),action:"reopen.issue",payload:{id:s.id},...e.data});return a(d)?d:c("Issue reopened",null)},onSuccess:()=>I({mode:p.DEFAULT})},{intent:b.SetUserName,mode:p.COMMAND_LINE,action:()=>{let{userId:e,preferredEditor:t,userName:n}=ie(),r=nt()?.trim();if(!r)return i("No username provided");let o=r??n,s=e??F();if(!o||!s)return i("Unable to resolve user name or id");let d=an({userName:o,userId:s,preferredEditor:t??""});return a(d)?d:(Dt({userName:o,userId:s}),I({mode:p.DEFAULT}),c(`Username set to "${r}"`,null))}},{intent:b.Init,mode:p.COMMAND_LINE,action:()=>{let e=cn();if(a(e))return e;let{rootNodeId:t,nodes:n}=y();return O.navigate({currentNode:n[t],selectedIndex:0}),c("Project initialized",null)}},{intent:b.SetEditor,mode:p.COMMAND_LINE,action:()=>{let e=nt()?.trim();if(!e)return i("No editor provided");let t=an({preferredEditor:e});return a(t)?t:(Dt({preferredEditor:e}),I({mode:p.DEFAULT}),c(`Editor configuration set to "${e}"`,null))}},{intent:b.NewItem,mode:p.COMMAND_LINE,action:(e,t)=>{let n=H();if(a(n))return i("Unable to resolve user ID");if(!t.inputString)return i(`provide a name for your ${t.modifier}`);let{breadCrumb:r,currentNode:o,selectedIndex:s}=y(),d=l=>{let u=K(l);if(a(u))return u;let f=N.getNode(u.data.result.id);if(!f)return i("Created node not found");if(!f.parentNodeId)return u;let v=N.getNode(f.parentNodeId);return v?(O.navigate({currentNode:v,selectedIndex:N.getSiblings(f.parentNodeId).findIndex(({id:E})=>E===f.id)}),u):i("Parent node not found")};if(t.modifier==="board"){let{rootNodeId:l}=y(),u=N.getNode(l);return u?d({id:F(),action:"add.board",payload:{id:F(),name:t.inputString,parent:u.id},...n.data}):i("Workspace not found")}if(t.modifier==="swimlane"){let l=ve(r,"BOARD");return a(l)?i("Unable to add swimlane in this context"):d({id:F(),action:"add.swimlane",payload:{id:F(),name:t.inputString,parent:l.data.id},...n.data})}if(t.modifier==="issue"){let l=A(o.id)[s],u=o.context==="SWIMLANE"?o:o.context==="BOARD"&&l?.context==="SWIMLANE"?l:(()=>{let R=ve(r,"SWIMLANE");return a(R)?null:R.data})();if(!u)return i("Unable to add issue in this context");let f=st({name:t.inputString,parent:u.id,user:n.data}),v=Re(f);if(v.some(R=>a(R)))return i("Issue create failed: "+v.filter(a).map(R=>R.message).filter(Boolean).join(", "));let E=v[0];if(!E||a(E))return i("Issue creation failed");let C=f[0]?.payload.id;return C?(O.navigate({currentNode:u,selectedIndex:N.getSiblings(u.id).findIndex(({id:R})=>R===C)}),c("Issue created",null)):i("Unable to determine ticket id")}return pn()},onSuccess:()=>I({mode:p.DEFAULT})},{intent:b.SetView,mode:p.COMMAND_LINE,action:()=>{let{commandMeta:e}=te();return e.validity===oe.Invalid?i("Invalid command "+Z):(j(t=>({...t,viewMode:e.modifier==="wide"?"wide":e.modifier==="dense"?"dense":t.viewMode})),c("View set",null))},onSuccess:()=>I({mode:p.DEFAULT})},{intent:b.Rename,mode:p.COMMAND_LINE,action:()=>{let e=H();if(a(e))return i("Unable to resolve user ID");let{currentNode:t,selectedIndex:n}=y(),r=A(t.id)[n];if(!r)return i("Missing node");if(r.readonly)return i("Cannot rename readonly node");let o=nt();return o?K({id:F(),action:"edit.title",payload:{id:r.id,name:o},...e.data}):i("Provide a new name")},onSuccess:()=>I({mode:p.DEFAULT})},{intent:b.TagTicket,mode:p.COMMAND_LINE,action:()=>{let e=H();if(a(e))return i("Unable to resolve user ID");let{modifier:t,inputString:n}=te().commandMeta,r=(t||n).trim();if(!r)return i("Provide a tag");let{selectedIndex:o,currentNode:s}=y(),d=A(s.id)[o];if(!d)return i("Invalid tag target");let l=Ye(d.id,"TICKET");if(a(l))return i("Unable to tag issue in this context");let u=l.data,f=is(r),v;if(f)v=f.id;else{let R=F(),M=K({id:F(),action:"create.tag",payload:{id:R,name:r},userId:e.data.userId,userName:e.data.userName});if(a(M))return M;v=M.data.result.id}let E=N.getFieldByTitle(u.id,"Tags");return E?A(E.id).some(R=>R.props?.value===v)?i("Already tagged with that tag"):K({id:F(),action:"tag.issue",payload:{id:F(),target:u.id,tagId:v},...e.data}):i("Unable to locate tags field")},onSuccess:()=>I({mode:p.DEFAULT})},{intent:b.AssignUserToTicket,mode:p.COMMAND_LINE,action:()=>{let e=H();if(a(e))return i("Unable to resolve user ID");let{modifier:t,inputString:n}=te().commandMeta,r=(t||n).trim();if(!r)return i("Provide an assignee");let{selectedIndex:o,currentNode:s}=y(),d=A(s.id)[o];if(!d)return i("Invalid assign target");let l=Ye(d.id,"TICKET");if(a(l))return i("Unable to assign issue in this context");let u=l.data,f=ss(r),v;if(f)v=f.id;else{let R=F(),M=K({id:F(),action:"create.contributor",payload:{id:R,name:r},userId:e.data.userId,userName:e.data.userName});if(a(M))return M;v=M.data.result.id}let E=N.getFieldByTitle(u.id,"Assignees");return E?A(E.id).some(R=>R.props?.value===v)?i("Assignee already assigned"):K({id:F(),action:"assign.issue",payload:{id:F(),target:u.id,contributor:v},...e.data}):i("Unable to locate assignees field")},onSuccess:()=>I({mode:p.DEFAULT})},{intent:b.Sync,mode:p.COMMAND_LINE,action:async()=>{D(()=>""),I({syncStatus:{msg:"Syncing",status:"syncing"}});let{userId:e,userName:t}=ie();if(!e)return i("Unable to resolve userId");if(!t)return i("Unable to resolve userName");let n=Fe()?cn():c("No pending default events",null);if(a(n))return i(`Unable to persist default events. ${n.message}`);let r=H();if(a(r)||!r.data)return i("Unable to resolve event log path");let o=_e(r.data);logger.debug("[sync-command] pending defaults",Fe());let s=await It({ownEventFileName:o});if(a(s))return I({syncStatus:{msg:s.message,status:"outOfSync"}}),i(`Unable to sync state. ${s.message}`);I({syncStatus:{msg:"Synced",status:"synced"},mode:p.DEFAULT});let d=We();return a(d)?i("Unable to load events"):(Ee(d.data),c("Synced",!0))}},{intent:b.Peek,mode:p.COMMAND_LINE,action:async()=>{let e=ve(y().breadCrumb,"BOARD");if(a(e))return e;let t=We();if(a(t))return i(t.message);let n=t.data,{modifier:r}=te().commandMeta,o;if(r==="now"){let E=dn();if(a(E))return E;let C=Ee(n);return C.some(a)?i(C.map(R=>R.message).join(", ")):(I({mode:p.DEFAULT,readOnly:!1,timeMode:"live",unappliedEvents:[]}),c("Peeking now",!0))}if(r==="prev"){let E=y().eventLog.at(-2),C=Ft(E);if(C===null)return i("No previous event to peek");o=C}else if(r==="next"){let E=y().unappliedEvents.at(0),C=Ft(E);if(C===null)return i("No next event to peek");o=C}else{let E=Ze(r);if(!E)return i("Invalid peek date");o=E.getTime()}let s=e.data.id,{appliedEvents:d,unappliedEvents:l}=nr(n,o),u=dn();if(a(u))return u;let f=Ee(d);if(f.some(a))return i(f.map(E=>E.message).join(", "));let v=y().nodes[s];return v?(O.navigate({currentNode:v,selectedIndex:0}),I({mode:p.DEFAULT,readOnly:!0,timeMode:"peek",unappliedEvents:l}),c("Peeking ",!0)):i("Board did not exist at peek date")}}];var as=new Set(["peek","filter","view-help"]),G=async({isForceExecutedBySystem:e=!1}={})=>{let{commandMeta:{command:t,validity:n,modifier:r,inputString:o}}=te();if(!t)return i("No command to confirm");if(!e&&n===oe.Invalid)return i("Invalid command");let s=Vn(t);if(Bn(),y().readOnly&&!as.has(s))return Oe({result:Z.Fail,message:"Command not available in readonly state",data:null});let d=Wr.filter(u=>e||u.systemOnly!==!0).find(u=>u.intent===s);if(!d)return Oe({result:Z.Fail,message:"Command not found",data:null});let l=await d.action(d,{command:t,inputString:o,modifier:r});return a(l)?Oe(l):($n({addToHistory:!e}),d.onSuccess?.(),Oe(l))};var bt=[{intent:h.Exit,mode:p.MOVE,description:"[<Esc>] exit context / cancel",action:()=>(I({mode:p.COMMAND_LINE}),D(()=>"move cancel"),G({isForceExecutedBySystem:!0}))},{intent:h.InitMove,mode:p.DEFAULT,description:"[m] move init/confirm",action:()=>(I({mode:p.COMMAND_LINE}),D(()=>"move start"),G({isForceExecutedBySystem:!0}))},{intent:h.ConfirmMove,mode:p.MOVE,action:()=>(I({mode:p.COMMAND_LINE}),D(()=>"move confirm"),G({isForceExecutedBySystem:!0}))}],ht=[{intent:h.MovePreviousItem,mode:p.MOVE,action:()=>pe()?(I({mode:p.COMMAND_LINE}),D(()=>"move previous"),G({isForceExecutedBySystem:!0})):i("No pending move")},{intent:h.MoveNextItem,mode:p.MOVE,action:()=>pe()?(I({mode:p.COMMAND_LINE}),D(()=>"move next"),G({isForceExecutedBySystem:!0})):i("No pending move")}],Br=[{intent:h.MoveToNextContainer,mode:p.MOVE,action:()=>pe()?(I({mode:p.COMMAND_LINE}),D(()=>"move to-next"),G({isForceExecutedBySystem:!0})):i("No pending move")},{intent:h.MoveToPreviousContainer,mode:p.MOVE,action:()=>pe()?(I({mode:p.COMMAND_LINE}),D(()=>"move to-previous"),G({isForceExecutedBySystem:!0})):i("No pending move")}];var $r={[P.WORKSPACE]:[...bt,...ht],[P.BOARD]:[...bt,...ht],[P.SWIMLANE]:[...bt,...ht,...Br],[P.TICKET]:[],[P.FIELD]:[],[P.FIELD_LIST]:[],[P.TEXT]:[]};var Hr=[{intent:h.AddItem,mode:p.DEFAULT,description:"[n] new...",action:()=>(I({mode:p.COMMAND_LINE}),D(()=>`${m.NEW} `),c("Adding new item",null))},{intent:h.Delete,mode:p.DEFAULT,description:"[d] delete",action:()=>(I({mode:p.COMMAND_LINE}),D(()=>`${m.DELETE} `),c("Deleting item",null))},{intent:h.InitCommandLine,mode:p.DEFAULT,description:"[:] focus command line",action:()=>(I({mode:p.COMMAND_LINE}),D(()=>""),c("Entering command line mode",null))},{intent:h.Confirm,mode:p.DEFAULT,description:"[<Enter>] confirm/enter",action:()=>(O.enterChildNode(),c("Entering context",null))},{intent:h.Exit,mode:p.DEFAULT,description:"[q] exit context",action:()=>(O.enterParentNode(),c("Exiting context",null))},{intent:h.NavPreviousItem,mode:p.DEFAULT,description:"[arrows/hjkl] navigate",action:()=>(O.navigateToPreviousItem(),c("Navigating to previous item",null))},{intent:h.NavNextItem,mode:p.DEFAULT,action:()=>(O.navigateToNextItem(),c("Navigating to next item",null))},{intent:h.NavToPreviousContainer,mode:p.DEFAULT,action:()=>(O.navigateToPreviousContainer(),c("Navigating to previous container",null))},{intent:h.NavToNextContainer,mode:p.DEFAULT,action:()=>(O.navigateToNextContainer(),c("Navigating to next container",null))},{intent:h.Edit,mode:p.DEFAULT,action:()=>(I({mode:p.COMMAND_LINE}),D(()=>"edit"),G(),c("Fired command",!0))},{intent:h.SetViewDense,mode:p.DEFAULT,description:"[v] view change (wide/dense)",action:()=>(I({viewMode:"dense"}),c("View set",null))},{intent:h.SetViewWide,mode:p.DEFAULT,action:()=>(I({viewMode:"wide"}),c("View set",null))},{intent:h.Sync,mode:p.DEFAULT,description:"[s] sync epiq with remote state branch",action:()=>(I({mode:p.COMMAND_LINE}),D(()=>"sync"),G({isForceExecutedBySystem:!0}),c("Synced",!0))}];var Kr=[{intent:h.ViewHelp,mode:p.DEFAULT,action:()=>(I({mode:p.HELP}),c("Viewing help",null))},{intent:h.Exit,mode:p.HELP,action:()=>(I({mode:p.DEFAULT}),c("Exiting help",null))},{intent:h.Confirm,mode:p.COMMAND_LINE,action:()=>(G(),c("Executing command",null))},{intent:h.MoveCursorLeft,mode:p.COMMAND_LINE,action:()=>(Ht(-1),c("Moving cursor left",null))},{intent:h.MoveCursorRight,mode:p.COMMAND_LINE,action:()=>(Ht(1),c("Moving cursor right",null))},{intent:h.MoveCursorLeftOfWord,mode:p.COMMAND_LINE,action:()=>(Kt("left"),c("Moving cursor left of word",null))},{intent:h.MoveCursorRightOfWord,mode:p.COMMAND_LINE,action:()=>(Kt("right"),c("Moving cursor right of word",null))},{intent:h.ExitCommandLine,mode:p.COMMAND_LINE,action:()=>(I({mode:p.DEFAULT}),c("Exiting command line",null))},{intent:h.AutoCompleteCommand,mode:p.COMMAND_LINE,action:()=>(D((e,{remainder:t})=>t?e+t:e),c("Auto-completing command",null))},{intent:h.CaptureInput,mode:p.COMMAND_LINE,action:(e,{sequence:t})=>(D(n=>n+t),c("Capturing input",null))},{intent:h.EraseInput,mode:p.COMMAND_LINE,action:()=>(_n(),c("Erasing input",null))},{intent:h.EraseInputWord,mode:p.COMMAND_LINE,action:()=>(Wn(),c("Erasing input word",null))},{intent:h.GetLastCommandFromHistory,mode:p.COMMAND_LINE,action:()=>(Hn(),c("Getting last command from history",null))},{intent:h.GetNextCommandFromHistory,mode:p.COMMAND_LINE,action:()=>(Kn(),c("Getting next command from history",null))}];import ds from"chalk";var Rt=": for command line",Vr="q to exit",jr=`${ds.hex(hn.accent)("m")} to confirm`,ln={[P.WORKSPACE]:[Rt],[P.BOARD]:[Rt],[P.BOARD+p.COMMAND_LINE]:[Rt],[P.SWIMLANE]:[Rt],[P.TICKET+p.HELP]:[Vr],[P.SWIMLANE+p.HELP]:[Vr],[P.TICKET]:[],[P.FIELD]:[],[P.SWIMLANE+p.MOVE]:[jr],[P.TICKET+p.MOVE]:[jr]};var St=e=>e.trim().toLocaleLowerCase(),cs=(e,t)=>{let n=N.getFieldByTitle(e,t);if(!n)return"";let r=n.props?.value;return typeof r=="string"?r:""},ls=e=>{let{tags:t}=y(),n=N.getFieldByTitle(e,"Tags");return n?V(n.id).map(r=>{let o=r.props?.value;return typeof o=="string"?t[o]?.name:void 0}).filter(r=>!!r):[]},us=e=>{let{contributors:t}=y(),n=N.getFieldByTitle(e,"Assignees");return n?V(n.id).map(r=>{let o=r.props?.value;return typeof o=="string"?t[o]?.name:void 0}).filter(r=>!!r):[]},zr=(e,t)=>{let n=t.value;if(!n)return!0;switch(t.target){case"title":return St(e.title??"").includes(n);case"description":return St(cs(e.id,"Description")).includes(n);case"tag":return ls(e.id).map(St).some(l=>l.includes(n));case"assignee":return us(e.id).map(St).some(l=>l.includes(n));default:return!0}};function qr(e,t,n){let r=t[e];if(!r)return i("buildBreadCrumb(): current node not found");let o=[],s=r;for(;s&&(o.push(s),!(s.id===n||!s.parentNodeId));)s=t[s.parentNodeId];let d=o[o.length-1];return!d||d.id!==n?i("buildBreadCrumb(): node is not connected to root"):(o.reverse(),c("Breadcrumb built",o))}var Gr=e=>{let t={};for(let n of e)n.intent&&(t[n.mode]||(t[n.mode]={}),t[n.mode][n.intent]=n);return t};var At,un,ms=new Set,Jr=()=>{for(let e of ms)e()};function Yr(e){let{currentNodeId:t,mode:n,rootNodeId:r,nodes:o,filters:s}=e;if(!t)return i("derive(): currentNodeId is missing");if(!r)return i("derive(): rootNode is missing");if(!o[r])return i("derive(): unable to find root node");let l=o[t];if(!l)return logger.error("Unable to derive state, currentNode not found"),i("Unable to derive state, currentNode not found");let u=qr(t,o,r);if(a(u))return logger.error(u.message),u;let f=u.data,{context:v}=l,E=ln[v+n]??ln[v]??[],C=[...Hr,...$r[v]??[],...Kr],R=Gr(C),M=ps(o,s),Q=M[t]?.[e.selectedIndex]??null;return c("Derived successfully",{...e,currentNode:l,breadCrumb:f,availableHints:E,availableActions:C,actionIndex:R,selectedNode:Q,renderedChildrenIndex:M})}var y=()=>(At||logger.error("State not initialized. Call initWorkspaceState() first.",new Error().stack),At);function zt(e){un=e;let t={readOnly:!1,filters:[],tags:{},contributors:{},viewMode:"dense",mode:p.DEFAULT,nodes:{[e.id]:e},rootNodeId:e.id,currentNodeId:e.id,renderedChildrenIndex:{},selectedIndex:-1,syncStatus:{status:"synced",msg:""},eventLog:[],unappliedEvents:[],timeMode:"live"},n=Yr(t);return a(n)?n:(At=n.data,Jr(),c("State initialized",null))}function j(e){let t=y(),n=e(t),r=Yr(n);return a(r)?i(r.message??"Unable to update state"):(At=r.data,Jr(),c("State updated",null))}var I=e=>j(t=>({...t,...e}));var ps=(e,t)=>{let n={};for(let r of Object.values(e))J(r)&&t.length>0&&!t.every(o=>zr(r,o))||!r.parentNodeId||r.isDeleted||((!r.parentNodeId||!n[r.parentNodeId])&&(n[r.parentNodeId]=[]),n[r.parentNodeId].push(r));for(let r of Object.keys(n))n[r].sort((o,s)=>{let d=e[o.id],l=e[s.id];return!d||!l?0:d.rank.localeCompare(l.rank)});return n},A=e=>y()?.renderedChildrenIndex[e]??[],dn=()=>un?zt(un):i("Cannot reset state: no initial workspace found");var O={exit(){process.exit(0)},enterChildNode(){let e=y(),t=e.currentNode,n=Math.max(0,e.selectedIndex),r=A(t.id)[n];!r||t.context==="FIELD"||O.navigate({currentNode:r,selectedIndex:A(r.id).length?0:-1})},enterParentNode(){let{currentNode:e,nodes:t}=y();if(!e.parentNodeId){logger.info("Missing parent node id");return}let n=t[e.parentNodeId];if(!n){logger.error("Parent not found");return}let r=A(n.id),o=r.findIndex(({id:d})=>d===e.id),s=r.length===0?-1:o>=0?o:0;O.navigate({currentNode:n,selectedIndex:s})},navigateToNextItem:()=>Xr(1),navigateToPreviousItem:()=>Xr(-1),navigateToNextContainer:()=>Qr(1),navigateToPreviousContainer:()=>Qr(-1),navigate:({currentNode:e=y().currentNode,selectedIndex:t})=>{I({currentNodeId:e.id,selectedIndex:t})}},Xr=e=>{let t=y(),n=A(t.currentNode.id).length;if(n===0)return;let o=(Math.max(0,t.selectedIndex)+e+n)%n;O.navigate({selectedIndex:o})},Qr=e=>{let{currentNode:t,nodes:n,selectedIndex:r}=y();if(!t.childNavigationAcrossParents)return;if(!t.parentNodeId){logger.error("Missing parent node id");return}let o=n[t.parentNodeId];if(!t||!o)return;let s=A(o.id),d=s.findIndex(C=>C.id===t.id);if(d<0)return;let l=s.at(d+e)??s.at(0);if(!l)return;let u=A(l.id),f=Math.max(0,u.length-1),v=Math.min(Math.max(0,r),f),E=u.length?v:-1;O.navigate({currentNode:l,selectedIndex:E})};var ce="system",le="ACTOR",Ve=gs(),ue=null;function fs(){let e=Object.values(y().nodes).find(r=>r.context==="WORKSPACE");if(!e)throw new Error("No workspace found in event log");let[t]=A(e.id),[n]=t?A(t.id):[];if(logger.debug("Boot navigation target:",{workspace:e?.id,firstBoard:t?.id,firstSwimlane:n?.id}),n){let r=y().renderedChildrenIndex?.[n.id]??[];return{currentNode:n,selectedIndex:r.length>0?0:-1}}else return t?{currentNode:t,selectedIndex:0}:e?{currentNode:e,selectedIndex:0}:{currentNode:y().nodes[y().rootNodeId],selectedIndex:0}}function vs(){let e=fs();O.navigate(e)}function ys(){let e=Ve(),t=Ve(),n=Ve(),r=Ve(),o=Ve();return[{id:de(),userId:ce,userName:le,action:"init.workspace",payload:{id:e,name:"Workspace"}},{id:de(),userId:ce,userName:le,action:"add.board",payload:{id:t,name:"Default",parent:e}},{id:de(),userId:ce,userName:le,action:"add.swimlane",payload:{id:n,name:"Todo",parent:t}},{id:de(),userId:ce,userName:le,action:"add.swimlane",payload:{id:r,name:"Review",parent:t}},{id:de(),userId:ce,userName:le,action:"add.swimlane",payload:{id:o,name:"Done",parent:t}},{id:de(),userId:ce,userName:le,action:"add.board",payload:{id:gt,name:"Closed",parent:e}},{id:de(),userId:ce,userName:le,action:"add.swimlane",payload:{id:X,name:"Closed",parent:gt}},{id:de(),userId:ce,userName:le,action:"lock.node",payload:{id:gt}},{id:de(),userId:ce,userName:le,action:"lock.node",payload:{id:X}}]}function Fe(){return ue!==null}function cn(){if(!ue||ue.length===0)return ue=null,c("No pending default events to persist",null);let e=ue.map(t=>lt({event:t})).filter(a);return e.length>0?i([Me.bold.red("Persisting default events failed"),"",...e.map((t,n)=>`${Me.dim.gray(`${n+1}.`)} ${Me.dim(t.message)}`),`
34
+ ${n.message}`):c("Staged remote own event file",void 0)},Sr=async({repoRoot:e,worktreeRoot:t})=>{let n=await Vi(e);return a(n)?i(n.message):(x.debug("[sync] create remote sync commit"),Yt({cwd:t,message:n.data}))},nn=async e=>{x.debug("[sync] push remote worktree");let t=await Zt(e);if(a(t))return i(t.message);let n=await T({args:t.data?["push"]:["push","-u",B,L],cwd:e});return x.debug("[sync] push result",n),a(n)?i(`Failed during remote push
35
+ ${n.message}`):c("Pushed remote",!0)},Ar=async({repoRoot:e,worktreeRoot:t,ensureUpstream:n})=>{x.debug("[sync] bootstrap remote storage",{repoRoot:e,worktreeRoot:t,ensureUpstream:n});let r=!1,o=[Wi(),await zi({repoRoot:e}),await Ji({repoRoot:e,worktreeRoot:t}),await Yi(t),await Xi(t),n?await Zi(t):c("Skipped remote upstream bootstrap",!1)];for(let s of o){if(a(s))return i(s.message);r=r||!!s.data}return x.debug("[sync] bootstrap changed",r),c(n?"Bootstrapped remote storage":"Bootstrapped remote storage (readonly)",r)},wr=(e,t)=>{for(let n of[Ae(e),Ae(t)]){let r=Ct(n);if(a(r))return i(r.message)}return c("Ensured remote layout",void 0)};var Qi=({repoRoot:e,worktreeRoot:t,ownEventFileName:n})=>{let r=He({root:e,fileName:n}),o=He({root:t,fileName:n});return Ke.existsSync(r)?(logger.debug("[sync] merge own event file to remote",{ownEventFileName:n,localFile:r,remoteFile:o}),It({sourceFile:r,targetFile:o})):(logger.debug("[sync] local own event file missing",r),c("Local own event file missing, nothing to merge",!1))},Tr=async({repoRoot:e,worktreeRoot:t,ownEventFileName:n})=>{let r=Qi({repoRoot:e,worktreeRoot:t,ownEventFileName:n});if(a(r))return i(r.message);let o=await fr(t);if(a(o))return i(o.message);if(!r.data&&!o.data)return c("Own event file already up to date in remote worktree",{createdCommit:!1});let s=await Rr({worktreeRoot:t,ownEventFileName:n});if(a(s))return i(s.message);let d=await Sr({repoRoot:e,worktreeRoot:t});return a(d)?i(d.message):c("Merged, staged, and committed own event file",{createdCommit:!0,commitSha:d.data})},Mr=({repoRoot:e,worktreeRoot:t,ownEventFileName:n})=>{let r=He({root:e,fileName:n}),o=He({root:t,fileName:n});logger.debug("[sync] own event file sizes",{local:Ke.existsSync(r)?Ke.statSync(r).size:0,remote:Ke.existsSync(o)?Ke.statSync(o).size:0})},bt=async({cwd:e=process.cwd(),ownEventFileName:t})=>{logger.debug("[sync] start write sync",{cwd:e,ownEventFileName:t});let n=await lr(e);if(a(n))return i(n.message);let r=n.data,o=Cr(r);logger.debug("[sync] resolved roots",{repoRoot:r,worktreeRoot:o});let s=await vr(r);if(a(s))return i(s.message);if(s.data)return i("Cannot run :sync while the repository is in detached HEAD state");if(t.includes("/")||t.includes("\\"))return i("Own event file must be a file name, not a path");if(!t.endsWith(".jsonl"))return i("Own event file must end with .jsonl");let d=await Xt(r);if(a(d))return i(d.message);if(d.data)return i("Cannot run :sync while a merge, rebase, cherry-pick, or revert is in progress in the current repo");let l=await br(r);if(a(l))return i(l.message);logger.debug("[sync] ensure initial commit changed",l.data);let u=await Ar({repoRoot:r,worktreeRoot:o,ensureUpstream:!0});if(a(u))return i(u.message);let v=await Xt(o);if(a(v))return i(v.message);if(v.data)return i("Cannot run :sync while a merge, rebase, cherry-pick, or revert is in progress in the remote worktree");let f=wr(r,o);if(a(f))return i(f.message);let E=!1,C,R=!1,M=!1,Q=!1;logger.debug("[sync] pull remote branch before local copy");let Lt=await Qt({cwd:o,remote:B,branch:L});if(a(Lt))return i(Lt.message);R=Lt.data,logger.debug("[sync] pulled remote",R);let Pt=hr({repoRoot:r,worktreeRoot:o});if(a(Pt))return i(Pt.message);Q=Pt.data,logger.debug("[sync] hydrated from remote",Q);let Le=await Tr({repoRoot:r,worktreeRoot:o,ownEventFileName:t});if(a(Le))return i(Le.message);if(E=Le.data.createdCommit,C=Le.data.commitSha,Mr({repoRoot:r,worktreeRoot:o,ownEventFileName:t}),logger.debug("[sync] sync own file result",Le.data),E||u.data){let fe=await nn(o),ze=fe;if(a(fe)&&gr(fe.message)){let mn=await Qt({cwd:o,remote:B,branch:L});if(a(mn))return i(mn.message);let Pe=await Tr({repoRoot:r,worktreeRoot:o,ownEventFileName:t});if(a(Pe))return i(Pe.message);Pe.data.createdCommit&&(E=!0,C=Pe.data.commitSha),Mr({repoRoot:r,worktreeRoot:o,ownEventFileName:t}),logger.debug("[sync] retry sync own file result",Pe.data),ze=await nn(o)}if(a(ze))return i(ze.message);M=ze.data,logger.debug("[sync] pushed remote",M)}else logger.debug("[sync] no commit created, skipped push");if(E){let fe=await T({args:["rev-parse","HEAD"],cwd:o});if(a(fe))return i(fe.message);C=fe.data.stdout.trim()}return c("Synced event logs with remote",{repoRoot:r,worktreeRoot:o,createdCommit:E,commitSha:C,pulled:R,pushed:M,hydrated:Q,bootstrapped:u.data})};import{ulid as Lr}from"ulid";var we=null,pe=()=>structuredClone(we),Te=e=>we=e,Pr=()=>{let{currentNode:e,selectedIndex:t}=y(),r=A(e.id)[t];return r?c("Resolved selected child",r):i("Target node not found")};function rn(e){let t=Pr();if(a(t))return t;let{currentNode:n,nodes:r}=y();if(!n.parentNodeId)return i("Missing parent node id");let o=r[n.parentNodeId];if(!o)return i("Missing parent node");let s=V(o.id),d=s.findIndex(({id:C})=>C===n.id);if(d<0)return i("Current node not found among siblings");let l=s[d+e];if(!l)return i("Missing sibling node");let u=H();if(a(u))return i("Unable to resolve user ID");let{userId:v,userName:f}=u.data;if(Te({id:Lr(),userId:v,userName:f,action:"move.node",payload:{id:t.data.id,parent:l.id,pos:{at:"end"}}}),!we)return i("Could not materialize move state");let E=he(we,!0);return a(E)?E:c("Node moved successfully",E.data)}function on(e){let t=Pr();if(a(t))return t;let{currentNode:n,selectedIndex:r}=y(),s=V(n.id)[r+e];if(!s)return i("Missing sibling node");let d=H();if(a(d))return i("Unable to resolve user ID");let{userId:l,userName:u}=d.data;if(Te({id:Lr(),userId:l,userName:u,action:"move.node",payload:{id:t.data.id,parent:n.id,pos:{at:e===1?"after":"before",sibling:s.id}}}),!we)return i("Could not materialize move state");let v=he(we,!0);return a(v)?v:c("Node moved successfully",v.data)}import es from"node:os";import Dr from"node:path";import{z as Ve}from"zod";var ts={userId:"",userName:"",preferredEditor:"",autoSync:!1},Fr=Ve.object({preferredEditor:Ve.string().optional(),userName:Ve.string().optional(),userId:Ve.string().optional(),autoSync:Ve.boolean().optional()}).strict(),ns=".epiq",rs="config.json",kr=()=>Dr.join(es.homedir(),ns),sn=()=>Dr.join(kr(),rs),an=()=>{try{return q.mkDir(kr()),c("Ensured ~/.epiq exists",null)}catch{return i("Unable to create ~/.epiq")}},os=e=>{let t;try{t=JSON.parse(e)}catch{return i("Invalid ~/.epiq/config.json JSON")}let n=Fr.safeParse(t??{});return n.success?c("Parsed config",n.data):i(`Invalid ~/.epiq/config.json shape: ${n.error.issues.map(r=>r.path.join(".")||r.message).join(", ")}`)},Or=()=>{let e=an();if(a(e))return i(e.message);let t=sn(),n=q.readFile(t);return n==null||n.trim()===""?c("No config found, using empty config",{autoSync:!1,preferredEditor:"",userId:"",userName:""}):os(n)},Ur=e=>{let t=an();if(a(t))return i(t.message);let n=Fr.safeParse(e);if(!n.success)return i(`Invalid config: ${n.error.issues.map(o=>o.path.join(".")||o.message).join(", ")}`);let r=sn();try{return q.writeToFile(r,JSON.stringify(n.data,null,2)+`
36
+ `),c("Config written",null)}catch{return i("Unable to write ~/.epiq/config.json")}},ht=e=>{let t=Or();if(a(t))return i("Failed to read existing config");let n={...t.data,...e};return Ur(n)},_r=()=>{let e=sn(),t=an();if(a(t))return i("Unable to create ~/.epiq");if(!(q.readFile(e)!==null)){let u=Ur(ts);if(a(u))throw new Error("Unable to create ~/.epiq/config.json")}let r=Or();if(a(r))throw new Error(r.message||"Unable to load settings");let{preferredEditor:o,userName:s,userId:d,autoSync:l}=r.data;return!s||!d?i("User name or ID not configured in ~/.epiq/config.json"):c("successfully loaded settings",{preferredEditor:o??"",userName:s,userId:d,autoSync:l??!1})};var is=e=>Object.values(y().tags).find(t=>t.name===e),ss=e=>Object.values(y().contributors).find(t=>t.name===e),Wr=[{systemOnly:!0,intent:b.Move,mode:p.COMMAND_LINE,action:()=>{let e=H();if(a(e))return i("Unable to resolve user ID");let{modifier:t}=X().commandMeta,n=()=>{let l=pe();if(!l)return i("No pending move state");let u=l.payload.id;if(!y().nodes[u])return i("Moved node not found");let f=l.payload.parent,E=y().nodes[f];if(!E)return i("Move parent not found");let C=A(f).findIndex(R=>R.id===u);return C===-1?i("Moved node not found among rendered children"):(O.navigate({currentNode:E,selectedIndex:C}),c("Synchronized navigation to moved node",null))},r=l=>{if(a(l))return i(l.message);let u=n();return a(u)?i(u.message):c("Updated move preview",null)},{currentNode:o,selectedIndex:s}=y(),d=A(o.id)[s];if(!d)return I({mode:p.DEFAULT}),i("No move target");if(t==="start"){if(d.readonly)return i("Target node is read-only");if(s===-1)return i("No item selected");if(!d.parentNodeId)return i("Target has no parent");let l=A(d.parentNodeId),u=l.findIndex(({id:R})=>R===d.id);if(u===-1)return i("Target not found among siblings");let v=l[u-1],f=l[u+1],E=f!=null?{at:"before",sibling:f.id}:v!=null?{at:"after",sibling:v.id}:{at:"start"};Te({id:D(),action:"move.node",payload:{id:d.id,parent:d.parentNodeId,pos:E},...e.data}),I({mode:p.MOVE});let C=n();return a(C)?i(C.message):c("Move initialized",null)}if(t==="next")return I({mode:p.MOVE}),r(on(1));if(t==="previous")return I({mode:p.MOVE}),r(on(-1));if(t==="to-next")return I({mode:p.MOVE}),r(rn(1));if(t==="to-previous")return I({mode:p.MOVE}),r(rn(-1));if(t==="confirm"){I({mode:p.DEFAULT});let l=pe();if(!l)return i("No pending move to confirm");let u=K(l);if(a(u))return u;let v=n();return a(v)?i(v.message):(Te(null),c("Moved item",null))}return t==="cancel"?(Te(null),I({mode:p.DEFAULT}),c("Cancelling move",null)):i("Invalid move modifier")}},{intent:b.Delete,mode:p.COMMAND_LINE,action:()=>{let e=H();if(a(e))return i("Unable to resolve user ID");let{currentNode:t,selectedIndex:n}=y(),r=A(t.id)[n];return r?K({id:D(),action:"delete.node",payload:{id:r.id},...e.data}):i("Unable to resolve child to delete")},onSuccess:()=>I({mode:p.DEFAULT})},{intent:b.Edit,mode:p.COMMAND_LINE,action:()=>{let e=H();if(a(e))return i("Unable to resolve user ID");let t=ve(y().breadCrumb,"TICKET");if(a(t))return i("Edit target must be an issue");let n=t.data;if(n.readonly)return i("Cannot edit readonly field");let{currentNode:r,selectedIndex:o}=y();if(!A(n.id)[o])return i("No selected field");let d=A(r.id)[o];if(!d)return i("No selected field");if(d.readonly)return i("Cannot edit readonly field");let l=d.props.value;if(typeof l!="string")return i("Selected field is not editable text");let u=Jn(l);if(a(u))return i("Failed to edit field");let v=u.data;return v===l?c("No changes made",null):d.title==="Description"?K({id:D(),action:"edit.description",payload:{id:d.id,md:v},...e.data}):d.title==="Title"?K({id:D(),action:"edit.title",payload:{id:d.id,name:v},...e.data}):i(`Editing not supported for "${d.title}"`)},onSuccess:()=>I({mode:p.DEFAULT})},{intent:b.Filter,mode:p.COMMAND_LINE,action:()=>{let{modifier:e,inputString:t}=X().commandMeta,n=/(!=|=)/,[r,o]=e.split(n);if(!r||!(l=>_(m.FILTER).map(u=>u.split(n)[0]).includes(l))(r))return i("Invalid filter modifier");let d={target:r,operator:"=",value:t.trim()};return j(l=>({...l,filters:e==="clear"?[]:[...l.filters,d],mode:p.DEFAULT})),c("Viewing help",null)}},{intent:b.ViewHelp,mode:p.COMMAND_LINE,action:()=>(I({mode:p.HELP}),c("Viewing help",null))},{intent:b.CloseIssue,mode:p.COMMAND_LINE,action:()=>{let e=H();if(a(e))return i("Unable to resolve user ID");let{currentNode:t,selectedIndex:n}=y(),r=A(t.id)[n];if(!r)return i("Unable to close issue, no target found");if(!r.parentNodeId)return i("No target parent found");if(!J(r))return i("Cannot close in this context");let o=K({id:D(),action:"close.issue",payload:{id:r.id,parent:r.parentNodeId},...e.data});return a(o)?o:c("Viewing help",null)}},{intent:b.ReopenIssue,mode:p.COMMAND_LINE,action:()=>{let e=H();if(a(e))return i("Unable to resolve user ID");let{currentNode:t,selectedIndex:n}=y(),r=A(t.id)[n];if(!r)return i("Unable to reopen issue, no target found");let o=r.context==="TICKET"?c("Resolved ticket",r):et(r.id,"TICKET");if(a(o))return i("Cannot reopen in this context");let s=o.data,d=K({id:D(),action:"reopen.issue",payload:{id:s.id},...e.data});return a(d)?d:c("Issue reopened",null)},onSuccess:()=>I({mode:p.DEFAULT})},{intent:b.SetUserName,mode:p.COMMAND_LINE,action:()=>{let{userId:e,preferredEditor:t,userName:n}=ie(),r=at()?.trim();if(!r)return i("No username provided");let o=r??n,s=e??D();if(!o||!s)return i("Unable to resolve user name or id");let d=ht({userName:o,userId:s,preferredEditor:t??""});return a(d)?d:(nt({userName:o,userId:s}),I({mode:p.DEFAULT}),c(`Username set to "${r}"`,null))}},{intent:b.Init,mode:p.COMMAND_LINE,action:()=>{let e=cn();if(a(e))return e;let{rootNodeId:t,nodes:n}=y();return O.navigate({currentNode:n[t],selectedIndex:0}),c("Project initialized",null)}},{intent:b.SetEditor,mode:p.COMMAND_LINE,action:()=>{let e=at()?.trim();if(!e)return i("No editor provided");let t=ht({preferredEditor:e});return a(t)?t:(nt({preferredEditor:e}),I({mode:p.DEFAULT}),c(`Editor configuration set to "${e}"`,null))}},{intent:b.SetAutoSync,mode:p.COMMAND_LINE,action:()=>{let e=X().commandMeta.modifier;if(e!=="true"&&e!=="false")return i("Invalid response");let t=e.toLowerCase()==="true",n=ht({autoSync:t});return a(n)?n:(nt({autoSync:t}),I({mode:p.DEFAULT}),c(`Auto synchronization set to "${t}"`,null))}},{intent:b.NewItem,mode:p.COMMAND_LINE,action:(e,t)=>{let n=H();if(a(n))return i("Unable to resolve user ID");if(!t.inputString)return i(`provide a name for your ${t.modifier}`);let{breadCrumb:r,currentNode:o,selectedIndex:s}=y(),d=l=>{let u=K(l);if(a(u))return u;let v=N.getNode(u.data.result.id);if(!v)return i("Created node not found");if(!v.parentNodeId)return u;let f=N.getNode(v.parentNodeId);return f?(O.navigate({currentNode:f,selectedIndex:N.getSiblings(v.parentNodeId).findIndex(({id:E})=>E===v.id)}),u):i("Parent node not found")};if(t.modifier==="board"){let{rootNodeId:l}=y(),u=N.getNode(l);return u?d({id:D(),action:"add.board",payload:{id:D(),name:t.inputString,parent:u.id},...n.data}):i("Workspace not found")}if(t.modifier==="swimlane"){let l=ve(r,"BOARD");return a(l)?i("Unable to add swimlane in this context"):d({id:D(),action:"add.swimlane",payload:{id:D(),name:t.inputString,parent:l.data.id},...n.data})}if(t.modifier==="issue"){let l=A(o.id)[s],u=o.context==="SWIMLANE"?o:o.context==="BOARD"&&l?.context==="SWIMLANE"?l:(()=>{let R=ve(r,"SWIMLANE");return a(R)?null:R.data})();if(!u)return i("Unable to add issue in this context");let v=Je({name:t.inputString,parent:u.id,user:n.data}),f=Re(v);if(f.some(R=>a(R)))return i("Issue create failed: "+f.filter(a).map(R=>R.message).filter(Boolean).join(", "));let E=f[0];if(!E||a(E))return i("Issue creation failed");let C=v[0]?.payload.id;return C?(O.navigate({currentNode:u,selectedIndex:N.getSiblings(u.id).findIndex(({id:R})=>R===C)}),c("Issue created",null)):i("Unable to determine ticket id")}return pn()},onSuccess:()=>I({mode:p.DEFAULT})},{intent:b.SetView,mode:p.COMMAND_LINE,action:()=>{let{commandMeta:e}=X();return e.validity===oe.Invalid?i("Invalid command "+ee):(j(t=>({...t,viewMode:e.modifier==="wide"?"wide":e.modifier==="dense"?"dense":t.viewMode})),c("View set",null))},onSuccess:()=>I({mode:p.DEFAULT})},{intent:b.Rename,mode:p.COMMAND_LINE,action:()=>{let e=H();if(a(e))return i("Unable to resolve user ID");let{currentNode:t,selectedIndex:n}=y(),r=A(t.id)[n];if(!r)return i("Missing node");if(r.readonly)return i("Cannot rename readonly node");let o=at();return o?K({id:D(),action:"edit.title",payload:{id:r.id,name:o},...e.data}):i("Provide a new name")},onSuccess:()=>I({mode:p.DEFAULT})},{intent:b.TagTicket,mode:p.COMMAND_LINE,action:()=>{let e=H();if(a(e))return i("Unable to resolve user ID");let{modifier:t,inputString:n}=X().commandMeta,r=(t||n).trim();if(!r)return i("Provide a tag");let{selectedIndex:o,currentNode:s}=y(),d=A(s.id)[o];if(!d)return i("Invalid tag target");let l=et(d.id,"TICKET");if(a(l))return i("Unable to tag issue in this context");let u=l.data,v=is(r),f;if(v)f=v.id;else{let R=D(),M=K({id:D(),action:"create.tag",payload:{id:R,name:r},userId:e.data.userId,userName:e.data.userName});if(a(M))return M;f=M.data.result.id}let E=N.getFieldByTitle(u.id,"Tags");return E?A(E.id).some(R=>R.props?.value===f)?i("Already tagged with that tag"):K({id:D(),action:"tag.issue",payload:{id:D(),target:u.id,tagId:f},...e.data}):i("Unable to locate tags field")},onSuccess:()=>I({mode:p.DEFAULT})},{intent:b.AssignUserToTicket,mode:p.COMMAND_LINE,action:()=>{let e=H();if(a(e))return i("Unable to resolve user ID");let{modifier:t,inputString:n}=X().commandMeta,r=(t||n).trim();if(!r)return i("Provide an assignee");let{selectedIndex:o,currentNode:s}=y(),d=A(s.id)[o];if(!d)return i("Invalid assign target");let l=et(d.id,"TICKET");if(a(l))return i("Unable to assign issue in this context");let u=l.data,v=ss(r),f;if(v)f=v.id;else{let R=D(),M=K({id:D(),action:"create.contributor",payload:{id:R,name:r},userId:e.data.userId,userName:e.data.userName});if(a(M))return M;f=M.data.result.id}let E=N.getFieldByTitle(u.id,"Assignees");return E?A(E.id).some(R=>R.props?.value===f)?i("Assignee already assigned"):K({id:D(),action:"assign.issue",payload:{id:D(),target:u.id,contributor:f},...e.data}):i("Unable to locate assignees field")},onSuccess:()=>I({mode:p.DEFAULT})},{intent:b.Sync,mode:p.COMMAND_LINE,action:async()=>{k(()=>""),I({syncStatus:{msg:"Syncing",status:"syncing"}});let{userId:e,userName:t}=ie();if(!e)return i("Unable to resolve userId");if(!t)return i("Unable to resolve userName");let n=Fe()?cn():c("No pending default events",null);if(a(n))return i(`Unable to persist default events. ${n.message}`);let r=H();if(a(r)||!r.data)return i("Unable to resolve event log path");let o=_e(r.data);logger.debug("[sync-command] pending defaults",Fe());let s=await bt({ownEventFileName:o});if(a(s))return I({syncStatus:{msg:s.message,status:"outOfSync"}}),i(`Unable to sync state. ${s.message}`);I({syncStatus:{msg:"Synced",status:"synced"},mode:p.DEFAULT});let d=We();return a(d)?i("Unable to load events"):(Ee(d.data),c("Synced",!0))}},{intent:b.Peek,mode:p.COMMAND_LINE,action:async()=>{let e=ve(y().breadCrumb,"BOARD");if(a(e))return e;let t=We();if(a(t))return i(t.message);let n=t.data,{modifier:r}=X().commandMeta,o;if(r==="now"){let E=dn();if(a(E))return E;let C=Ee(n);return C.some(a)?i(C.map(R=>R.message).join(", ")):(I({mode:p.DEFAULT,readOnly:!1,timeMode:"live",unappliedEvents:[]}),c("Peeking now",!0))}if(r==="prev"){let E=y().eventLog.at(-2),C=kt(E);if(C===null)return i("No previous event to peek");o=C}else if(r==="next"){let E=y().unappliedEvents.at(0),C=kt(E);if(C===null)return i("No next event to peek");o=C}else{let E=ot(r);if(!E)return i("Invalid peek date");o=E.getTime()}let s=e.data.id,{appliedEvents:d,unappliedEvents:l}=nr(n,o),u=dn();if(a(u))return u;let v=Ee(d);if(v.some(a))return i(v.map(E=>E.message).join(", "));let f=y().nodes[s];return f?(O.navigate({currentNode:f,selectedIndex:0}),I({mode:p.DEFAULT,readOnly:!0,timeMode:"peek",unappliedEvents:l}),c("Peeking ",!0)):i("Board did not exist at peek date")}}];var as=new Set(["peek","filter","view-help"]),G=async({isForceExecutedBySystem:e=!1}={})=>{let{commandMeta:{command:t,validity:n,modifier:r,inputString:o}}=X();if(!t)return i("No command to confirm");if(!e&&n===oe.Invalid)return i("Invalid command");let s=Vn(t);if(Bn(),y().readOnly&&!as.has(s))return Oe({result:ee.Fail,message:"Command not available in readonly state",data:null});let d=Wr.filter(u=>e||u.systemOnly!==!0).find(u=>u.intent===s);if(!d)return Oe({result:ee.Fail,message:"Command not found",data:null});let l=await d.action(d,{command:t,inputString:o,modifier:r});return a(l)?Oe(l):($n({addToHistory:!e}),d.onSuccess?.(),Oe(l))};var Rt=[{intent:h.Exit,mode:p.MOVE,description:"[<Esc>] exit context / cancel",action:()=>(I({mode:p.COMMAND_LINE}),k(()=>"move cancel"),G({isForceExecutedBySystem:!0}))},{intent:h.InitMove,mode:p.DEFAULT,description:"[m] move init/confirm",action:()=>(I({mode:p.COMMAND_LINE}),k(()=>"move start"),G({isForceExecutedBySystem:!0}))},{intent:h.ConfirmMove,mode:p.MOVE,action:()=>(I({mode:p.COMMAND_LINE}),k(()=>"move confirm"),G({isForceExecutedBySystem:!0}))}],St=[{intent:h.MovePreviousItem,mode:p.MOVE,action:()=>pe()?(I({mode:p.COMMAND_LINE}),k(()=>"move previous"),G({isForceExecutedBySystem:!0})):i("No pending move")},{intent:h.MoveNextItem,mode:p.MOVE,action:()=>pe()?(I({mode:p.COMMAND_LINE}),k(()=>"move next"),G({isForceExecutedBySystem:!0})):i("No pending move")}],Br=[{intent:h.MoveToNextContainer,mode:p.MOVE,action:()=>pe()?(I({mode:p.COMMAND_LINE}),k(()=>"move to-next"),G({isForceExecutedBySystem:!0})):i("No pending move")},{intent:h.MoveToPreviousContainer,mode:p.MOVE,action:()=>pe()?(I({mode:p.COMMAND_LINE}),k(()=>"move to-previous"),G({isForceExecutedBySystem:!0})):i("No pending move")}];var $r={[P.WORKSPACE]:[...Rt,...St],[P.BOARD]:[...Rt,...St],[P.SWIMLANE]:[...Rt,...St,...Br],[P.TICKET]:[],[P.FIELD]:[],[P.FIELD_LIST]:[],[P.TEXT]:[]};var Hr=[{intent:h.AddItem,mode:p.DEFAULT,description:"[n] new...",action:()=>(I({mode:p.COMMAND_LINE}),k(()=>`${m.NEW} `),c("Adding new item",null))},{intent:h.Delete,mode:p.DEFAULT,description:"[d] delete",action:()=>(I({mode:p.COMMAND_LINE}),k(()=>`${m.DELETE} `),c("Deleting item",null))},{intent:h.InitCommandLine,mode:p.DEFAULT,description:"[:] focus command line",action:()=>(I({mode:p.COMMAND_LINE}),k(()=>""),c("Entering command line mode",null))},{intent:h.Confirm,mode:p.DEFAULT,description:"[<Enter>] confirm/enter",action:()=>(O.enterChildNode(),c("Entering context",null))},{intent:h.Exit,mode:p.DEFAULT,description:"[q] exit context",action:()=>(O.enterParentNode(),c("Exiting context",null))},{intent:h.NavPreviousItem,mode:p.DEFAULT,description:"[arrows/hjkl] navigate",action:()=>(O.navigateToPreviousItem(),c("Navigating to previous item",null))},{intent:h.NavNextItem,mode:p.DEFAULT,action:()=>(O.navigateToNextItem(),c("Navigating to next item",null))},{intent:h.NavToPreviousContainer,mode:p.DEFAULT,action:()=>(O.navigateToPreviousContainer(),c("Navigating to previous container",null))},{intent:h.NavToNextContainer,mode:p.DEFAULT,action:()=>(O.navigateToNextContainer(),c("Navigating to next container",null))},{intent:h.Edit,mode:p.DEFAULT,action:()=>(I({mode:p.COMMAND_LINE}),k(()=>"edit"),G(),c("Fired command",!0))},{intent:h.SetViewDense,mode:p.DEFAULT,description:"[v] view change (wide/dense)",action:()=>(I({viewMode:"dense"}),c("View set",null))},{intent:h.SetViewWide,mode:p.DEFAULT,action:()=>(I({viewMode:"wide"}),c("View set",null))}];var Kr=[{intent:h.ViewHelp,mode:p.DEFAULT,action:()=>(I({mode:p.HELP}),c("Viewing help",null))},{intent:h.Exit,mode:p.HELP,action:()=>(I({mode:p.DEFAULT}),c("Exiting help",null))},{intent:h.Confirm,mode:p.COMMAND_LINE,action:()=>(G(),c("Executing command",null))},{intent:h.MoveCursorLeft,mode:p.COMMAND_LINE,action:()=>(Kt(-1),c("Moving cursor left",null))},{intent:h.MoveCursorRight,mode:p.COMMAND_LINE,action:()=>(Kt(1),c("Moving cursor right",null))},{intent:h.MoveCursorLeftOfWord,mode:p.COMMAND_LINE,action:()=>(Vt("left"),c("Moving cursor left of word",null))},{intent:h.MoveCursorRightOfWord,mode:p.COMMAND_LINE,action:()=>(Vt("right"),c("Moving cursor right of word",null))},{intent:h.ExitCommandLine,mode:p.COMMAND_LINE,action:()=>(I({mode:p.DEFAULT}),c("Exiting command line",null))},{intent:h.AutoCompleteCommand,mode:p.COMMAND_LINE,action:()=>(k((e,{remainder:t})=>t?e+t:e),c("Auto-completing command",null))},{intent:h.CaptureInput,mode:p.COMMAND_LINE,action:(e,{sequence:t})=>(k(n=>n+t),c("Capturing input",null))},{intent:h.EraseInput,mode:p.COMMAND_LINE,action:()=>(_n(),c("Erasing input",null))},{intent:h.EraseInputWord,mode:p.COMMAND_LINE,action:()=>(Wn(),c("Erasing input word",null))},{intent:h.GetLastCommandFromHistory,mode:p.COMMAND_LINE,action:()=>(Hn(),c("Getting last command from history",null))},{intent:h.GetNextCommandFromHistory,mode:p.COMMAND_LINE,action:()=>(Kn(),c("Getting next command from history",null))}];import ds from"chalk";var At=": for command line",Vr="q to exit",jr=`${ds.hex(hn.accent)("m")} to confirm`,ln={[P.WORKSPACE]:[At],[P.BOARD]:[At],[P.BOARD+p.COMMAND_LINE]:[At],[P.SWIMLANE]:[At],[P.TICKET+p.HELP]:[Vr],[P.SWIMLANE+p.HELP]:[Vr],[P.TICKET]:[],[P.FIELD]:[],[P.SWIMLANE+p.MOVE]:[jr],[P.TICKET+p.MOVE]:[jr]};var wt=e=>e.trim().toLocaleLowerCase(),cs=(e,t)=>{let n=N.getFieldByTitle(e,t);if(!n)return"";let r=n.props?.value;return typeof r=="string"?r:""},ls=e=>{let{tags:t}=y(),n=N.getFieldByTitle(e,"Tags");return n?V(n.id).map(r=>{let o=r.props?.value;return typeof o=="string"?t[o]?.name:void 0}).filter(r=>!!r):[]},us=e=>{let{contributors:t}=y(),n=N.getFieldByTitle(e,"Assignees");return n?V(n.id).map(r=>{let o=r.props?.value;return typeof o=="string"?t[o]?.name:void 0}).filter(r=>!!r):[]},zr=(e,t)=>{let n=t.value;if(!n)return!0;switch(t.target){case"title":return wt(e.title??"").includes(n);case"description":return wt(cs(e.id,"Description")).includes(n);case"tag":return ls(e.id).map(wt).some(l=>l.includes(n));case"assignee":return us(e.id).map(wt).some(l=>l.includes(n));default:return!0}};function qr(e,t,n){let r=t[e];if(!r)return i("buildBreadCrumb(): current node not found");let o=[],s=r;for(;s&&(o.push(s),!(s.id===n||!s.parentNodeId));)s=t[s.parentNodeId];let d=o[o.length-1];return!d||d.id!==n?i("buildBreadCrumb(): node is not connected to root"):(o.reverse(),c("Breadcrumb built",o))}var Gr=e=>{let t={};for(let n of e)n.intent&&(t[n.mode]||(t[n.mode]={}),t[n.mode][n.intent]=n);return t};var Tt,un,ms=new Set,Jr=()=>{for(let e of ms)e()};function Yr(e){let{currentNodeId:t,mode:n,rootNodeId:r,nodes:o,filters:s}=e;if(!t)return i("derive(): currentNodeId is missing");if(!r)return i("derive(): rootNode is missing");if(!o[r])return i("derive(): unable to find root node");let l=o[t];if(!l)return logger.error("Unable to derive state, currentNode not found"),i("Unable to derive state, currentNode not found");let u=qr(t,o,r);if(a(u))return logger.error(u.message),u;let v=u.data,{context:f}=l,E=ln[f+n]??ln[f]??[],C=[...Hr,...$r[f]??[],...Kr],R=Gr(C),M=ps(o,s),Q=M[t]?.[e.selectedIndex]??null;return c("Derived successfully",{...e,currentNode:l,breadCrumb:v,availableHints:E,availableActions:C,actionIndex:R,selectedNode:Q,renderedChildrenIndex:M})}var y=()=>(Tt||logger.error("State not initialized. Call initWorkspaceState() first.",new Error().stack),Tt);function qt(e){un=e;let t={readOnly:!1,filters:[],tags:{},contributors:{},viewMode:"dense",mode:p.DEFAULT,nodes:{[e.id]:e},rootNodeId:e.id,currentNodeId:e.id,renderedChildrenIndex:{},selectedIndex:-1,syncStatus:{status:"synced",msg:""},eventLog:[],unappliedEvents:[],timeMode:"live"},n=Yr(t);return a(n)?n:(Tt=n.data,Jr(),c("State initialized",null))}function j(e){let t=y(),n=e(t),r=Yr(n);return a(r)?i(r.message??"Unable to update state"):(Tt=r.data,Jr(),c("State updated",null))}var I=e=>j(t=>({...t,...e}));var ps=(e,t)=>{let n={};for(let r of Object.values(e))J(r)&&t.length>0&&!t.every(o=>zr(r,o))||!r.parentNodeId||r.isDeleted||((!r.parentNodeId||!n[r.parentNodeId])&&(n[r.parentNodeId]=[]),n[r.parentNodeId].push(r));for(let r of Object.keys(n))n[r].sort((o,s)=>{let d=e[o.id],l=e[s.id];return!d||!l?0:d.rank.localeCompare(l.rank)});return n},A=e=>y()?.renderedChildrenIndex[e]??[],dn=()=>un?qt(un):i("Cannot reset state: no initial workspace found");var O={exit(){process.exit(0)},enterChildNode(){let e=y(),t=e.currentNode,n=Math.max(0,e.selectedIndex),r=A(t.id)[n];!r||t.context==="FIELD"||O.navigate({currentNode:r,selectedIndex:A(r.id).length?0:-1})},enterParentNode(){let{currentNode:e,nodes:t}=y();if(!e.parentNodeId){logger.info("Missing parent node id");return}let n=t[e.parentNodeId];if(!n){logger.error("Parent not found");return}let r=A(n.id),o=r.findIndex(({id:d})=>d===e.id),s=r.length===0?-1:o>=0?o:0;O.navigate({currentNode:n,selectedIndex:s})},navigateToNextItem:()=>Xr(1),navigateToPreviousItem:()=>Xr(-1),navigateToNextContainer:()=>Zr(1),navigateToPreviousContainer:()=>Zr(-1),navigate:({currentNode:e=y().currentNode,selectedIndex:t})=>{I({currentNodeId:e.id,selectedIndex:t})}},Xr=e=>{let t=y(),n=A(t.currentNode.id).length;if(n===0)return;let o=(Math.max(0,t.selectedIndex)+e+n)%n;O.navigate({selectedIndex:o})},Zr=e=>{let{currentNode:t,nodes:n,selectedIndex:r}=y();if(!t.childNavigationAcrossParents)return;if(!t.parentNodeId){logger.error("Missing parent node id");return}let o=n[t.parentNodeId];if(!t||!o)return;let s=A(o.id),d=s.findIndex(C=>C.id===t.id);if(d<0)return;let l=s.at(d+e)??s.at(0);if(!l)return;let u=A(l.id),v=Math.max(0,u.length-1),f=Math.min(Math.max(0,r),v),E=u.length?f:-1;O.navigate({currentNode:l,selectedIndex:E})};var ce="system",le="ACTOR",je=gs(),ue=null;function fs(){let e=Object.values(y().nodes).find(r=>r.context==="WORKSPACE");if(!e)throw new Error("No workspace found in event log");let[t]=A(e.id),[n]=t?A(t.id):[];if(logger.debug("Boot navigation target:",{workspace:e?.id,firstBoard:t?.id,firstSwimlane:n?.id}),n){let r=y().renderedChildrenIndex?.[n.id]??[];return{currentNode:n,selectedIndex:r.length>0?0:-1}}else return t?{currentNode:t,selectedIndex:0}:e?{currentNode:e,selectedIndex:0}:{currentNode:y().nodes[y().rootNodeId],selectedIndex:0}}function vs(){let e=fs();O.navigate(e)}function ys(){let e=je(),t=je(),n=je(),r=je(),o=je();return[{id:de(),userId:ce,userName:le,action:"init.workspace",payload:{id:e,name:"Workspace"}},{id:de(),userId:ce,userName:le,action:"add.board",payload:{id:t,name:"Default",parent:e}},{id:de(),userId:ce,userName:le,action:"add.swimlane",payload:{id:n,name:"Todo",parent:t}},{id:de(),userId:ce,userName:le,action:"add.swimlane",payload:{id:r,name:"In progress",parent:t}},{id:de(),userId:ce,userName:le,action:"add.swimlane",payload:{id:o,name:"Done",parent:t}},{id:de(),userId:ce,userName:le,action:"add.board",payload:{id:vt,name:"Closed",parent:e}},{id:de(),userId:ce,userName:le,action:"add.swimlane",payload:{id:Z,name:"Closed",parent:vt}},{id:de(),userId:ce,userName:le,action:"lock.node",payload:{id:vt}},{id:de(),userId:ce,userName:le,action:"lock.node",payload:{id:Z}}]}function Fe(){return ue!==null}function cn(){if(!ue||ue.length===0)return ue=null,c("No pending default events to persist",null);let e=ue.map(t=>mt({event:t})).filter(a);return e.length>0?i([Me.bold.red("Persisting default events failed"),"",...e.map((t,n)=>`${Me.dim.gray(`${n+1}.`)} ${Me.dim(t.message)}`),`
37
37
  `].join(`
38
- `)):(ue=null,c("Persisted pending default events",null))}function Zr(e){let t;e.some(r=>r.action==="init.workspace")?(ue=null,t=Ee(e)):(ue=ys(),t=Ee([...ue]));let n=t.filter(a);return n.length>0?i([Me.bold.red("Materializing failed"),"",...n.map((r,o)=>`${Me.dim.gray(`${o+1}.`)} ${Me.dim(r.message)}`),`
38
+ `)):(ue=null,c("Persisted pending default events",null))}function Qr(e){let t;e.some(r=>r.action==="init.workspace")?(ue=null,t=Ee(e)):(ue=ys(),t=Ee([...ue]));let n=t.filter(a);return n.length>0?i([Me.bold.red("Materializing failed"),"",...n.map((r,o)=>`${Me.dim.gray(`${o+1}.`)} ${Me.dim(r.message)}`),`
39
39
  `].join(`
40
- `)):(vs(),c("State booted successfully",null))}var eo=(e,t)=>{let r=A(e.id).find(o=>o.title===t);return r&&typeof r.props?.value=="string"?qe(r.props.value):""};var xe=e=>{let t=ae(e??process.cwd()),n=We(t);if(a(n))return i(n.message);let r=Zr(n.data);return a(r)?i(r.message):c("Booted Epiq state",{root:t})},wt=()=>{let e=_r();return a(e)?i(e.message):e.data.userId?e.data.userName?c("Resolved actor",{userId:e.data.userId,userName:e.data.userName}):i("Unable to retrieve user name"):i("Unable to retrieve user id")},no=(e,t)=>{let r=A(e.id).find(o=>o.title===t);return r?A(r.id).map(o=>typeof o.props?.value=="string"?o.props.value:"").filter(o=>!!o):[]},Es=e=>no(e,"Tags").map(t=>N.getTag(t)).filter(t=>t!=null).map(t=>({id:t.id,name:t.name})),Ns=e=>no(e,"Assignees").map(t=>N.getContributor(t)).filter(t=>t!=null).map(t=>({id:t.id,name:t.name})),ro=(e={})=>{let t=xe(e.repoRoot);if(a(t))return t;let n=Object.values(y().nodes).filter(r=>r.context==="BOARD").map(r=>({id:r.id,title:r.title,parentId:r.parentNodeId,readonly:!!r.readonly}));return c("Listed boards",n)},oo=(e={})=>{let t=xe(e.repoRoot);if(a(t))return t;let n=Object.values(y().nodes).filter(r=>r.context==="SWIMLANE").filter(r=>!e.boardId||r.parentNodeId===e.boardId).map(r=>({id:r.id,title:r.title,boardId:r.parentNodeId,isClosed:r.id===X,readonly:!!r.readonly}));return c("Listed swimlanes",n)},io=e=>{let t=xe(e.repoRoot);if(a(t))return t;let n=Object.values(y().nodes).filter(J).filter(r=>e.includeClosed||r.parentNodeId!==X).map(r=>({id:r.id,title:qe(r.title),description:eo(r,"Description"),parentId:r.parentNodeId,isClosed:r.parentNodeId===X,readonly:!!r.readonly,tags:Es(r),assignees:Ns(r)}));return c("Listed issues",n)},so=e=>{let t=xe(e.repoRoot);if(a(t))return t;let n=wt();if(a(n))return n;let r=N.getNode(e.parentId);if(!r)return i(`Unable to locate parent swimlane: ${e.parentId}`);if(r.context!=="SWIMLANE")return i(`Parent must be a swimlane, got: ${r.context}`);let o=st({name:e.title,parent:e.parentId,user:n.data}),d=Re(o).find(a);if(d)return i(d.message);let l=o.find(u=>u.action==="add.issue")?.payload.id;return l?c("Created issue",{id:l,title:e.title,parentId:e.parentId}):i("Unable to determine created issue id")},ao=e=>{let t=xe(e.repoRoot);if(a(t))return t;let n=wt();if(a(n))return n;let r=N.getNode(e.issueId);if(!r)return i(`Unable to locate issue: ${e.issueId}`);if(!r.parentNodeId)return i(`Unable to locate issue parent for: ${e.issueId}`);if(!J(r))return i("Can only close issues");if(r.parentNodeId===X)return i("Issue is already closed");let o={id:to(),userId:n.data.userId,userName:n.data.userName,action:"close.issue",payload:{id:e.issueId,parent:r.parentNodeId}},d=Re([o]).find(a);return d?i(d.message):c("Closed issue",{id:e.issueId,closed:!0})},co=(e={})=>{let t=xe(e.repoRoot);return a(t)?t:c("Retrieved Epiq state",{root:t.data.root,nodes:y().nodes,rootNodeId:y().rootNodeId,currentNode:y().currentNode,selectedIndex:y().selectedIndex,eventLog:y().eventLog})},lo=e=>{let t=xe(e.repoRoot);if(a(t))return t;let n=wt();if(a(n))return n;let r=N.getNode(e.issueId);if(!r)return i(`Unable to locate issue: ${e.issueId}`);if(!J(r))return i("Can only move issues");let o=N.getNode(e.parentId);if(!o)return i(`Unable to locate target swimlane: ${e.parentId}`);if(o.context!=="SWIMLANE")return i(`Target parent must be a swimlane, got: ${o.context}`);if(o.readonly)return i("Cannot move issue to readonly swimlane");let s={id:to(),userId:n.data.userId,userName:n.data.userName,action:"move.node",payload:{id:e.issueId,parent:e.parentId,...e.position==null?{}:{pos:e.position}}},l=Re([s]).find(a);return l?i(l.message):c("Moved issue",{id:e.issueId,parentId:e.parentId,position:e.position??{at:"end"}})},uo=async(e={})=>{let t=ae(e.repoRoot??process.cwd()),n=wt();if(a(n))return n;let r=await It({cwd:t,ownEventFileName:_e({userId:n.data.userId,userName:n.data.userName})});return a(r)?r:c("Synced Epiq state",r.data)};var ge=e=>({isError:a(e),content:[{type:"text",text:JSON.stringify(e,null,2)}]}),Cs=()=>{let e=new xs({name:"epiq",version:"0.2.30"});return e.registerTool("epiq_state_get",{description:"Get the full current Epiq state, including nodes and event log",inputSchema:S.object({repoRoot:S.string().optional()})},async t=>ge(await co(t))),e.registerTool("epiq_issue_list",{description:"List Epiq issues",inputSchema:S.object({repoRoot:S.string().optional(),includeClosed:S.boolean().optional()})},async t=>ge(await io(t))),e.registerTool("epiq_board_list",{description:"List Epiq boards",inputSchema:S.object({repoRoot:S.string().optional()})},async t=>ge(await ro(t))),e.registerTool("epiq_swimlane_list",{description:"List Epiq swimlanes",inputSchema:S.object({repoRoot:S.string().optional(),boardId:S.string().optional()})},async t=>ge(await oo(t))),e.registerTool("epiq_issue_create",{description:"Create an Epiq issue",inputSchema:S.object({title:S.string().min(1),parentId:S.string().min(1),repoRoot:S.string().optional()})},async t=>ge(await so(t))),e.registerTool("epiq_issue_close",{description:"Close an Epiq issue",inputSchema:S.object({issueId:S.string().min(1),repoRoot:S.string().optional()})},async t=>ge(await ao(t))),e.registerTool("epiq_issue_move",{description:"Move an Epiq issue to another swimlane",inputSchema:S.object({issueId:S.string().min(1),parentId:S.string().min(1),position:S.discriminatedUnion("at",[S.object({at:S.literal("start")}),S.object({at:S.literal("end")}),S.object({at:S.literal("before"),sibling:S.string().min(1)}),S.object({at:S.literal("after"),sibling:S.string().min(1)})]).optional(),repoRoot:S.string().optional()})},async t=>ge(await lo(t))),e.registerTool("epiq_sync",{description:"Sync Epiq state with the configured Git remote",inputSchema:S.object({repoRoot:S.string().optional()})},async t=>ge(await uo(t))),e},bs=async()=>{let e=Cs(),t=new Is;await e.connect(t)};await bs();export{Cs as createMcpServer,ge as resultJson,bs as startMcpServer};
40
+ `)):(vs(),c("State booted successfully",null))}var eo=(e,t)=>{let r=A(e.id).find(o=>o.title===t);return r&&typeof r.props?.value=="string"?Xe(r.props.value):""};var xe=e=>{let t=ae(e??process.cwd()),n=We(t);if(a(n))return i(n.message);let r=Qr(n.data);return a(r)?i(r.message):c("Booted Epiq state",{root:t})},Mt=()=>{let e=_r();return a(e)?i(e.message):e.data.userId?e.data.userName?c("Resolved actor",{userId:e.data.userId,userName:e.data.userName}):i("Unable to retrieve user name"):i("Unable to retrieve user id")},no=(e,t)=>{let r=A(e.id).find(o=>o.title===t);return r?A(r.id).map(o=>typeof o.props?.value=="string"?o.props.value:"").filter(o=>!!o):[]},Es=e=>no(e,"Tags").map(t=>N.getTag(t)).filter(t=>t!=null).map(t=>({id:t.id,name:t.name})),Ns=e=>no(e,"Assignees").map(t=>N.getContributor(t)).filter(t=>t!=null).map(t=>({id:t.id,name:t.name})),ro=(e={})=>{let t=xe(e.repoRoot);if(a(t))return t;let n=Object.values(y().nodes).filter(r=>r.context==="BOARD").map(r=>({id:r.id,title:r.title,parentId:r.parentNodeId,readonly:!!r.readonly}));return c("Listed boards",n)},oo=(e={})=>{let t=xe(e.repoRoot);if(a(t))return t;let n=Object.values(y().nodes).filter(r=>r.context==="SWIMLANE").filter(r=>!e.boardId||r.parentNodeId===e.boardId).map(r=>({id:r.id,title:r.title,boardId:r.parentNodeId,isClosed:r.id===Z,readonly:!!r.readonly}));return c("Listed swimlanes",n)},io=e=>{let t=xe(e.repoRoot);if(a(t))return t;let n=Object.values(y().nodes).filter(J).filter(r=>e.includeClosed||r.parentNodeId!==Z).map(r=>({id:r.id,title:Xe(r.title),description:eo(r,"Description"),parentId:r.parentNodeId,isClosed:r.parentNodeId===Z,readonly:!!r.readonly,tags:Es(r),assignees:Ns(r)}));return c("Listed issues",n)},so=e=>{let t=xe(e.repoRoot);if(a(t))return t;let n=Mt();if(a(n))return n;let r=N.getNode(e.parentId);if(!r)return i(`Unable to locate parent swimlane: ${e.parentId}`);if(r.context!=="SWIMLANE")return i(`Parent must be a swimlane, got: ${r.context}`);let o=Je({name:e.title,parent:e.parentId,user:n.data}),d=Re(o).find(a);if(d)return i(d.message);let l=o.find(u=>u.action==="add.issue")?.payload.id;return l?c("Created issue",{id:l,title:e.title,parentId:e.parentId}):i("Unable to determine created issue id")},ao=e=>{let t=xe(e.repoRoot);if(a(t))return t;let n=Mt();if(a(n))return n;let r=N.getNode(e.issueId);if(!r)return i(`Unable to locate issue: ${e.issueId}`);if(!r.parentNodeId)return i(`Unable to locate issue parent for: ${e.issueId}`);if(!J(r))return i("Can only close issues");if(r.parentNodeId===Z)return i("Issue is already closed");let o={id:to(),userId:n.data.userId,userName:n.data.userName,action:"close.issue",payload:{id:e.issueId,parent:r.parentNodeId}},d=Re([o]).find(a);return d?i(d.message):c("Closed issue",{id:e.issueId,closed:!0})},co=(e={})=>{let t=xe(e.repoRoot);return a(t)?t:c("Retrieved Epiq state",{root:t.data.root,nodes:y().nodes,rootNodeId:y().rootNodeId,currentNode:y().currentNode,selectedIndex:y().selectedIndex,eventLog:y().eventLog})},lo=e=>{let t=xe(e.repoRoot);if(a(t))return t;let n=Mt();if(a(n))return n;let r=N.getNode(e.issueId);if(!r)return i(`Unable to locate issue: ${e.issueId}`);if(!J(r))return i("Can only move issues");let o=N.getNode(e.parentId);if(!o)return i(`Unable to locate target swimlane: ${e.parentId}`);if(o.context!=="SWIMLANE")return i(`Target parent must be a swimlane, got: ${o.context}`);if(o.readonly)return i("Cannot move issue to readonly swimlane");let s={id:to(),userId:n.data.userId,userName:n.data.userName,action:"move.node",payload:{id:e.issueId,parent:e.parentId,...e.position==null?{}:{pos:e.position}}},l=Re([s]).find(a);return l?i(l.message):c("Moved issue",{id:e.issueId,parentId:e.parentId,position:e.position??{at:"end"}})},uo=async(e={})=>{let t=ae(e.repoRoot??process.cwd()),n=Mt();if(a(n))return n;let r=await bt({cwd:t,ownEventFileName:_e({userId:n.data.userId,userName:n.data.userName})});return a(r)?r:c("Synced Epiq state",r.data)};var ge=e=>({isError:a(e),content:[{type:"text",text:JSON.stringify(e,null,2)}]}),Cs=()=>{let e=new xs({name:"epiq",version:"0.2.30"});return e.registerTool("epiq_state_get",{description:"Get the full current Epiq state, including nodes and event log",inputSchema:S.object({repoRoot:S.string().optional()})},async t=>ge(await co(t))),e.registerTool("epiq_issue_list",{description:"List Epiq issues",inputSchema:S.object({repoRoot:S.string().optional(),includeClosed:S.boolean().optional()})},async t=>ge(await io(t))),e.registerTool("epiq_board_list",{description:"List Epiq boards",inputSchema:S.object({repoRoot:S.string().optional()})},async t=>ge(await ro(t))),e.registerTool("epiq_swimlane_list",{description:"List Epiq swimlanes",inputSchema:S.object({repoRoot:S.string().optional(),boardId:S.string().optional()})},async t=>ge(await oo(t))),e.registerTool("epiq_issue_create",{description:"Create an Epiq issue",inputSchema:S.object({title:S.string().min(1),parentId:S.string().min(1),repoRoot:S.string().optional()})},async t=>ge(await so(t))),e.registerTool("epiq_issue_close",{description:"Close an Epiq issue",inputSchema:S.object({issueId:S.string().min(1),repoRoot:S.string().optional()})},async t=>ge(await ao(t))),e.registerTool("epiq_issue_move",{description:"Move an Epiq issue to another swimlane",inputSchema:S.object({issueId:S.string().min(1),parentId:S.string().min(1),position:S.discriminatedUnion("at",[S.object({at:S.literal("start")}),S.object({at:S.literal("end")}),S.object({at:S.literal("before"),sibling:S.string().min(1)}),S.object({at:S.literal("after"),sibling:S.string().min(1)})]).optional(),repoRoot:S.string().optional()})},async t=>ge(await lo(t))),e.registerTool("epiq_sync",{description:"Sync Epiq state with the configured Git remote",inputSchema:S.object({repoRoot:S.string().optional()})},async t=>ge(await uo(t))),e},bs=async()=>{let e=Cs(),t=new Is;await e.connect(t)};await bs();export{Cs as createMcpServer,ge as resultJson,bs as startMcpServer};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "epiq",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "license": "UNLICENSED",
5
5
  "type": "module",
6
6
  "description": "EPIQ - CLI based issue tracker",
@@ -42,7 +42,7 @@
42
42
  "pack:check": "rm -f epiq-*.tgz && npm pack && FILE=$(ls -t epiq-*.tgz | head -n 1) && echo \"$FILE\" && tar -tf \"$FILE\"",
43
43
  "publish:dry": "rm -f epiq-*.tgz && npm pack && FILE=$(ls -t epiq-*.tgz | head -n 1) && npm publish --dry-run \"$FILE\"",
44
44
  "publish:tarball": "FILE=$(ls -t epiq-*.tgz | head -n 1) && echo \"Publishing $FILE\" && npm publish \"$FILE\"",
45
- "release": "pnpm test && pnpm pack:check && pnpm publish:tarball",
45
+ "release": "pnpm pack:check && pnpm publish:tarball",
46
46
  "start:mcp": "IS_LOCAL=true tsx source/mcp/server.ts",
47
47
  "inspect:mcp": "pnpm dlx @modelcontextprotocol/inspector"
48
48
  },
package/readme.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  # Epiq
4
4
 
5
+ _Distributed CLI based issue tracker TUI_ backed by git.
6
+
5
7
  Issue tracking is a part of the development lifecycle, but it often becomes a painful context switching exercise with poor ergonomics. `Epiq` provides issue tracking as a portable, integrated part of the development environment, with access to all the powerful tooling developers are used to. Epiq is a **CLI-native issue tracker** — powered by Git in which you can manage all your projects directly via the command line in a visual kanban board and edit content in your favorite, personalized editor.
6
8
 
7
9
  With great attention to user ergonomics, epiq intends to make project management painless and friction free again, and has developer satisfaction as its primary target.
@@ -22,6 +24,9 @@ Epiq is a vim-inspired issue tracker fully integrated in the terminal that bring
22
24
 
23
25
  Epiq renders your issue board directly in the terminal using ASCII and stores its state as an event log, versioned and synchronized through Git.
24
26
 
27
+ ![Epiq cli kanban view](https://raw.githubusercontent.com/ljtn/epiq/main/resources/overview.png)
28
+ ![Epiq cli log view](https://raw.githubusercontent.com/ljtn/epiq/main/resources/log.png)
29
+
25
30
  ## Features
26
31
 
27
32
  - Issue tracking — track work in tickets with name, description, tags, assignees, history log, etc.
@@ -154,6 +159,9 @@ Clear all filters with `:filter clear`
154
159
 
155
160
  - Pro tip: just like in any terminal - if you need to do repeating tasks over and over again, you can just put yourself in the command mode, and then press arrow up, in order to access the last executed command. This helps a lot when you create tasks with similar names, or add the same tag to many tickets and so on.
156
161
 
162
+ Starting the application will launch a wizard that sets you up in 20 seconds.
163
+ It will result in settings persisted at `~/.epicrc`
164
+
157
165
  ---
158
166
 
159
167
  ## How epiq is synchronized