prjct-cli 3.39.0 → 3.40.0

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.
@@ -1193,7 +1193,7 @@ CREATE TABLE velocity_sprints (
1193
1193
  `);let r=new Set(e.prepare("SELECT version FROM _migrations").all().map(i=>i.version)),s=fi.filter(i=>!r.has(i.version));if(s.length!==0){if(t&&r.size>0)try{let i=`${t}.pre-migrate.bak`;ns.existsSync(i)&&ns.rmSync(i,{force:!0}),e.prepare("VACUUM INTO ?").run(i)}catch(i){console.warn(`prjct: pre-migration backup failed (continuing): ${i?.message??i}`)}for(let i of s)Pa(e,()=>{i.up(e),e.prepare("INSERT INTO _migrations (version, name, applied_at) VALUES (?, ?, ?)").run(i.version,i.name,new Date().toISOString())})}}getMigrations(e){return this.getDb(e).prepare("SELECT * FROM _migrations ORDER BY version").all()}getSchemaVersion(e){return this.getDb(e).prepare("SELECT MAX(version) as version FROM _migrations").get()?.version??0}},y=new hi,h=y});import Da from"node:fs/promises";import Tn from"node:path";function Op(n){let e=[],t,r=new RegExp(Bd.source,"g");for(;(t=r.exec(n))!==null;){let s=t[1];(s.startsWith(".")||s.startsWith("@/"))&&e.push(s)}return e}async function Lp(n,e,t){let r;if(n.startsWith("@/"))r=Tn.join(t,"src",n.slice(2));else{let s=Tn.dirname(Tn.join(t,e));r=Tn.resolve(s,n)}for(let s of Gd){let i=r+s;try{if((await Da.stat(i)).isFile())return Tn.relative(t,i)}catch{}}return null}async function hS(n){let e=await Vt(n),t={},r={},s=0,i=await Jt(e,50,async o=>{try{let c=await Da.readFile(Tn.join(n,o),"utf-8"),l=Op(c),u=[];for(let d of l){let p=await Lp(d,o,n);p&&p!==o&&u.push(p)}return u.length>0?{filePath:o,imports:u}:null}catch{return null}});for(let{filePath:o,imports:c}of i){t[o]=c,s+=c.length;for(let l of c)r[l]||(r[l]=[]),r[l].push(o)}return{forward:t,reverse:r,fileCount:e.length,edgeCount:s,builtAt:new Date().toISOString()}}function ki(n,e,t=2){let r=new Set(n),s=new Map,i=[];for(let o of n){let c=e.forward[o]||[],l=e.reverse[o]||[];for(let u of[...c,...l])r.has(u)||i.push({file:u,depth:1})}for(let o=0;o<i.length;o++){let{file:c,depth:l}=i[o];if(l>t)continue;let u=1/(l+1),d=s.get(c);if(d){u>d.score&&s.set(c,{score:u,depth:l});continue}if(s.set(c,{score:u,depth:l}),l<t){let p=e.forward[c]||[],m=e.reverse[c]||[];for(let g of[...p,...m])!r.has(g)&&!s.has(g)&&i.push({file:g,depth:l+1})}}return Array.from(s.entries()).map(([o,{score:c,depth:l}])=>({path:o,score:c,depth:l})).sort((o,c)=>c.score-o.score)}function yS(n){return Object.values(n).reduce((e,t)=>e+t.length,0)}function ES(n,e){let t=n.forward[e]||[];delete n.forward[e];for(let r of t){let s=(n.reverse[r]||[]).filter(i=>i!==e);s.length===0?delete n.reverse[r]:n.reverse[r]=s}}function kS(n,e){let t=n.reverse[e]||[];delete n.reverse[e];let r=[];for(let s of t){let i=(n.forward[s]||[]).filter(o=>o!==e);i.length===0?delete n.forward[s]:n.forward[s]=i,r.push(s)}return r}function TS(n,e,t){if(t.length===0)return;let r=Array.from(new Set(t));n.forward[e]=r;for(let s of r)n.reverse[s]||(n.reverse[s]=[]),n.reverse[s].includes(e)||n.reverse[s].push(e)}async function wS(n,e){try{let t=await Da.readFile(Tn.join(n,e),"utf-8"),r=Op(t),s=[];for(let i of r){let o=await Lp(i,e,n);o&&o!==e&&s.push(o)}return{filePath:e,imports:s}}catch{return null}}function jp(n){return{schemaVersion:2,fileCount:n.fileCount,edgeCount:n.edgeCount,builtAt:n.builtAt}}function SS(n,e){try{h.transaction(n,t=>{t.prepare("DELETE FROM import_graph_edges").run();let r=t.prepare("INSERT INTO import_graph_edges (from_path, to_path, sort_order) VALUES (?, ?, ?)");for(let[s,i]of Object.entries(e.forward))for(let[o,c]of i.entries())r.run(s,c,o)})}catch{}}function vS(n,e,t,r){try{h.transaction(n,s=>{let i=s.prepare("DELETE FROM import_graph_edges WHERE from_path = ?"),o=s.prepare("INSERT INTO import_graph_edges (from_path, to_path, sort_order) VALUES (?, ?, ?)");for(let c of new Set([...t,...r]))i.run(c);for(let c of t){let l=e.forward[c]||[];for(let[u,d]of l.entries())o.run(c,d,u)}})}catch{}}function bS(n,e,t){try{let r=h.query(n,"SELECT from_path, to_path FROM import_graph_edges ORDER BY from_path, sort_order, to_path");if(r.length===0){if(t?.edgeCount===0){let l={forward:{},reverse:{},fileCount:t.fileCount,edgeCount:0,builtAt:t.builtAt};return wn.set(n,{graph:l,updatedAt:e}),l}return null}let s={},i={};for(let l of r)s[l.from_path]||(s[l.from_path]=[]),s[l.from_path].push(l.to_path),i[l.to_path]||(i[l.to_path]=[]),i[l.to_path].push(l.from_path);let o=new Set;for(let[l,u]of Object.entries(s)){o.add(l);for(let d of u)o.add(d)}let c={forward:s,reverse:i,fileCount:t?.fileCount??o.size,edgeCount:r.length,builtAt:t?.builtAt??e};return wn.set(n,{graph:c,updatedAt:e}),c}catch{return null}}function _S(n,e){h.setDoc(n,Ei,jp(e)),SS(n,e),wn.delete(n)}function RS(n,e,t,r){h.setDoc(n,Ei,jp(e)),vS(n,e,t,r),wn.delete(n)}function it(n){let e=h.get(n,"SELECT updated_at FROM kv_store WHERE key = ?",Ei);if(!e)return wn.delete(n),null;let t=wn.get(n);if(t&&t.updatedAt===e.updated_at)return t.graph;let r=h.getDoc(n,Ei),s=bS(n,e.updated_at,r);if(s)return s;if(!r?.forward||!r?.reverse)return null;let i={forward:r.forward,reverse:r.reverse,fileCount:r.fileCount,edgeCount:r.edgeCount,builtAt:r.builtAt};return wn.set(n,{graph:i,updatedAt:e.updated_at}),i}async function rs(n,e){let t=await hS(n);return _S(e,t),t}async function Mp(n,e,t,r=[]){let s=it(e);if(!s)return rs(n,e);let i=new Set([...t,...r]);for(let l of i)ES(s,l);let o=new Set;for(let l of r)for(let u of kS(s,l))o.add(u);let c=await Jt(t,50,l=>wS(n,l));for(let l of c)TS(s,l.filePath,l.imports);return s.edgeCount=yS(s.forward),s.builtAt=new Date().toISOString(),RS(e,s,[...t,...o],r),s}var Ei,wn,rr=f(()=>{"use strict";ga();P();te();a(Op,"extractImportSources");a(Lp,"resolveImport");a(hS,"buildGraph");a(ki,"scoreFromSeeds");Ei="import-graph",wn=new Map;a(yS,"countEdges");a(ES,"removeOutgoingEdges");a(kS,"removeIncomingEdges");a(TS,"addEdges");a(wS,"importsForFile");a(jp,"graphMetadata");a(SS,"replacePerFileEdges");a(vS,"updatePerFileEdges");a(bS,"loadGraphFromPerFileEdges");a(_S,"saveGraph");a(RS,"saveGraphUpdate");a(it,"loadGraph");a(rs,"indexImports");a(Mp,"updateImportGraph")});function Ti(n,e){let t=[...n.added,...n.modified],r=new Set(t),s=new Set,i=it(e);if(i)for(let l of t){let u=i.reverse[l];if(u)for(let d of u)r.has(d)||s.add(d)}let o=Array.from(s),c=[...t,...o];return{directlyChanged:t,affectedByImports:o,deleted:n.deleted,allAffected:c}}function wi(n){let e=new Set;for(let t of n){let r=t.toLowerCase();(r.endsWith(".tsx")||r.endsWith(".jsx")||r.endsWith(".css")||r.endsWith(".scss")||r.endsWith(".vue")||r.endsWith(".svelte")||r.includes("/components/")||r.includes("/pages/")||r.includes("/app/"))&&(e.add("frontend"),e.add("uxui")),(r.includes(".test.")||r.includes(".spec.")||r.includes("__tests__")||r.includes("/test/"))&&e.add("testing"),(r.includes("dockerfile")||r.includes("docker-compose")||r.includes(".dockerignore")||r.includes(".github/")||r.includes("ci/")||r.includes("cd/"))&&e.add("devops"),(r.endsWith(".sql")||r.includes("prisma")||r.includes("drizzle")||r.includes("migration")||r.includes("/db/"))&&e.add("database"),(r.endsWith(".ts")||r.endsWith(".js"))&&!r.includes(".test.")&&!r.includes(".spec.")&&!r.endsWith(".d.ts")&&e.add("backend")}return e}var Oa=f(()=>{"use strict";rr();a(Ti,"propagateChanges");a(wi,"affectedDomains")});var La=f(()=>{"use strict"});async function AS(n,e=100){try{let{stdout:t}=await I(`git log --name-only --pretty=format:'---COMMIT---' -${e}`,{cwd:n,maxBuffer:10485760}),r=[],s=null;for(let i of t.split(`
1194
1194
  `)){let o=i.trim();o==="---COMMIT---"?(s&&s.size>0&&s.size<=30&&r.push(s),s=new Set):o&&s&&CS(o)&&s.add(o)}return s&&s.size>0&&s.size<=30&&r.push(s),r}catch{return[]}}function CS(n){return/\.(ts|tsx|js|jsx|mjs|cjs|py|go|rs|java|cs|rb|php|vue|svelte)$/i.test(n)&&!n.includes("node_modules/")}async function NS(n,e=100){let t=await AS(n,e),r=new Map,s=new Map;for(let o of t){let c=Array.from(o);for(let l of c)r.set(l,(r.get(l)||0)+1);for(let l=0;l<c.length;l++)for(let u=l+1;u<c.length;u++){let d=IS(c[l],c[u]);s.set(d,(s.get(d)||0)+1)}}let i={};for(let[o,c]of s){let[l,u]=o.split("\0"),d=r.get(l)||0,p=r.get(u)||0;if(d<2||p<2)continue;let m=d+p-c,g=m>0?c/m:0;g<.1||(i[l]||(i[l]={}),i[u]||(i[u]={}),i[l][u]=g,i[u][l]=g)}return{matrix:i,commitsAnalyzed:t.length,filesAnalyzed:r.size,builtAt:new Date().toISOString()}}function IS(n,e){return n<e?`${n}\0${e}`:`${e}\0${n}`}function ss(n,e){let t=new Set(n),r=new Map;for(let s of n){let i=e.matrix[s];if(i)for(let[o,c]of Object.entries(i)){if(t.has(o))continue;let l=r.get(o)||0;c>l&&r.set(o,c)}}return Array.from(r.entries()).map(([s,i])=>({path:s,score:i})).sort((s,i)=>i.score-s.score)}function PS(n,e){h.setDoc(n,ja,e),Si.delete(n)}function Pt(n){let e=h.get(n,"SELECT updated_at FROM kv_store WHERE key = ?",ja);if(!e)return Si.delete(n),null;let t=Si.get(n);if(t&&t.updatedAt===e.updated_at)return t.matrix;let r=h.getDoc(n,ja);return r&&Si.set(n,{matrix:r,updatedAt:e.updated_at}),r}async function DS(n,e){try{let{stdout:t}=await I(`git rev-list --max-count=${e} HEAD`,{cwd:n,maxBuffer:1048576}),r=t.split(`
1195
1195
  `).map(s=>s.trim()).filter(Boolean);return r.length>0?r.join(`
1196
- `):null}catch{return null}}async function vi(n,e,t=100){let r=await DS(n,t),s=r?Pt(e):null;if(s?.historyFingerprint===r)return s;let i=await NS(n,t);return r&&(i.historyFingerprint=r),PS(e,i),i}var ja,Si,is=f(()=>{"use strict";La();P();pe();a(AS,"parseGitLog");a(CS,"isSourceFile");a(NS,"buildMatrix");a(IS,"pairKey");a(ss,"scoreFromSeeds");ja="cochange-index",Si=new Map;a(PS,"saveMatrix");a(Pt,"loadMatrix");a(DS,"recentHistoryFingerprint");a(vi,"indexCoChanges")});function OS(n){return n instanceof os}function ke(n){return OS(n)||n instanceof Error?n.message:typeof n=="string"?n:"Unknown error"}var os,bi,as,Dt=f(()=>{"use strict";os=class extends Error{static{a(this,"PrjctError")}code;isOperational;constructor(e,t="PRJCT_ERROR"){super(e),this.name="PrjctError",this.code=t,this.isOperational=!0,Error.captureStackTrace?.(this,this.constructor)}},bi=class n extends os{static{a(this,"ProjectError")}constructor(e,t="PROJECT_ERROR"){super(e,t),this.name="ProjectError"}static notInitialized(){return new n("Project not initialized. Run p. init first.","PROJECT_NOT_INIT")}static notFound(e){return new n(`Project not found: ${e}`,"PROJECT_NOT_FOUND")}static invalidId(e){return new n(`Invalid project ID: ${e}`,"PROJECT_INVALID_ID")}},as=class n extends os{static{a(this,"AgentError")}constructor(e,t="AGENT_ERROR"){super(e,t),this.name="AgentError"}static notSupported(e){return new n(`Unsupported agent type: ${e}`,"AGENT_NOT_SUPPORTED")}static initFailed(e){return new n(`Agent initialization failed: ${e}`,"AGENT_INIT_FAILED")}};a(OS,"isPrjctError");a(ke,"getErrorMessage")});function Up(n){let e=n.toLowerCase();return e.includes("github")?"github":e.includes("gitlab")?"gitlab":e.includes("bitbucket")?"bitbucket":"other"}function Ma(n){let e=n.trim();if(!e)return{};let t=e.match(/^[^/@]+@([^:/]+):(.+?)(?:\.git)?\/?$/);if(t)return{provider:Up(t[1]),repoSlug:t[2]};try{let r=new URL(e),s=r.pathname.replace(/^\/+/,"").replace(/\.git$/,"").replace(/\/+$/,"");return!r.host||!s?{}:{provider:Up(r.host),repoSlug:s}}catch{return{}}}async function LS(n){try{let{stdout:e}=await G("git",["remote","get-url","origin"],{cwd:n});return e.trim()||void 0}catch{return}}async function jS(n){try{let{stdout:e}=await G("git",["symbolic-ref","--short","refs/remotes/origin/HEAD"],{cwd:n});return e.trim().replace(/^origin\//,"")||void 0}catch{return}}function Sn(n){return typeof n=="string"&&n.length>0?n:void 0}function Hp(n){return typeof n=="number"&&Number.isFinite(n)?n:void 0}function MS(n){return Object.fromEntries(Object.entries(n).filter(([,e])=>e!==void 0))}async function Wp(n){let e=y.getDoc(n,"project")||{},t=Sn(e.repoPath),{provider:r,repoSlug:s}=t?Ma(await LS(t)||""):{},i=t?await jS(t):void 0,o=Array.isArray(e.techStack)?e.techStack.filter(c=>typeof c=="string"):void 0;return MS({provider:r,repoSlug:s,currentBranch:Sn(e.currentBranch),defaultBranch:i,stack:Sn(e.stack),techStack:o&&o.length>0?o:void 0,version:Sn(e.version),commitCount:Hp(e.commitCount),fileCount:Hp(e.fileCount),lastCommit:Sn(e.lastSyncCommit),hasUncommitted:typeof e.hasUncommittedChanges=="boolean"?e.hasUncommittedChanges:void 0,cliVersion:Sn(e.cliVersion),syncedAt:Sn(e.lastSync)})}var Fa=f(()=>{"use strict";P();pe();a(Up,"providerForHost");a(Ma,"parseRemote");a(LS,"gitRemoteUrl");a(jS,"gitDefaultBranch");a(Sn,"str");a(Hp,"num");a(MS,"compact");a(Wp,"buildProjectMeta")});import{execFile as FS}from"node:child_process";import $S from"node:crypto";import{promisify as US}from"node:util";function GS(n,e=WS){let t=Buffer.from(e.replace(/-/g,""),"hex"),s=$S.createHash("sha1").update(t).update(n,"utf8").digest().subarray(0,16);s[6]=s[6]&15|80,s[8]=s[8]&63|128;let i=s.toString("hex");return`${i.slice(0,8)}-${i.slice(8,12)}-${i.slice(12,16)}-${i.slice(16,20)}-${i.slice(20,32)}`}async function BS(n){let e;try{let{stdout:s}=await HS("git",["remote","get-url","origin"],{cwd:n});e=s.trim()||void 0}catch{return null}if(!e)return null;let{provider:t,repoSlug:r}=Ma(e);return!t||!r?null:`${t}:${r}`.toLowerCase()}async function Gp(n){let e=await BS(n);return e?GS(e):null}var HS,WS,Bp=f(()=>{"use strict";Fa();HS=US(FS),WS="6f9b2c1a-3d4e-5f60-8a7b-1c2d3e4f5a6b";a(GS,"uuidv5");a(BS,"repoKey");a(Gp,"deriveProjectId")});var Ha={};q(Ha,{PACKAGE_ROOT:()=>nn,VERSION:()=>tn,getPackageRoot:()=>Ua,getVersion:()=>Ri,resetPackageRoot:()=>XS});import $a from"node:fs";import _i from"node:path";function Ua(){if(sr)return sr;let n=__dirname;for(let e=0;e<5;e++){let t=_i.join(n,"package.json");if($a.existsSync(t))try{if(JSON.parse($a.readFileSync(t,"utf-8")).name==="prjct-cli")return sr=n,n}catch{}n=_i.dirname(n)}return sr=_i.join(__dirname,"..","..",".."),sr}function Ri(){if(vn)return vn;let n="3.39.0";if(n&&/^\d+\.\d+\.\d+/.test(n))return vn=n,vn;try{let e=_i.join(Ua(),"package.json");return vn=JSON.parse($a.readFileSync(e,"utf-8")).version,vn}catch(e){return process.env.PRJCT_DEBUG==="1"&&console.error("Failed to read version from package.json:",v(e)),"0.0.0"}}function XS(n){sr=n,vn=null}var vn,sr,tn,nn,Ot=f(()=>{"use strict";ee();vn=null,sr=null;a(Ua,"getPackageRoot");a(Ri,"getVersion");a(XS,"resetPackageRoot");tn=Ri(),nn=Ua()});async function xi(n){try{let{stdout:e}=await I(n,{timeout:5e3});return{success:!0,output:e.trim()}}catch{return{success:!1,output:""}}}async function qS(){let n=await xi("gh api user --jq .login");return n.success&&n.output||(n=await xi("git config --global github.user"),n.success&&n.output)?n.output:null}async function VS(){let n=await xi("git config user.name");return n.success&&n.output?n.output:null}async function JS(){let n=await xi("git config user.email");return n.success&&n.output?n.output:null}async function ir(){let[n,e,t]=await Promise.all([qS(),VS(),JS()]);return{github:n,email:t,name:e||n||"Unknown"}}var Ai=f(()=>{"use strict";pe();a(xi,"execCommand");a(qS,"detectGitHubUsername");a(VS,"detectGitName");a(JS,"detectGitEmail");a(ir,"detect")});var Xa={};q(Xa,{worktreeService:()=>KS});import Ga from"node:fs/promises";import Et from"node:path";var Xp,Ba,KS,qa=f(()=>{"use strict";pe();te();Xp=".worktrees",Ba=class{static{a(this,"WorktreeService")}async create(e,t,r={}){let s=await this.getMainWorktree(e),i=Et.join(s,Xp,t),o=r.branch||`feat/${t}`;await Ga.mkdir(Et.join(s,Xp),{recursive:!0});let c=r.baseBranch?` ${r.baseBranch}`:"";await I(`git worktree add "${i}" -b "${o}"${c}`,{cwd:s});let{stdout:l}=await I("git rev-parse HEAD",{cwd:i});return{path:i,branch:o,commit:l.trim(),isMain:!1,slug:t}}async remove(e,t=!1){let r=await this.getMainWorktree(e),s;if(t)try{let{stdout:i}=await I("git rev-parse --abbrev-ref HEAD",{cwd:e});s=i.trim()}catch{}if(await I(`git worktree remove "${e}" --force`,{cwd:r}),t&&s&&s!=="main"&&s!=="master")try{await I(`git branch -D "${s}"`,{cwd:r})}catch{}}async list(e){let t=await this.getMainWorktree(e),{stdout:r}=await I("git worktree list --porcelain",{cwd:t});return this.parsePorcelainOutput(r,t)}async detect(e){try{let{stdout:t}=await I("git rev-parse --git-common-dir",{cwd:e}),{stdout:r}=await I("git rev-parse --git-dir",{cwd:e}),s=Et.resolve(e,t.trim()),i=Et.resolve(e,r.trim());if(s!==i){let{stdout:o}=await I("git rev-parse --abbrev-ref HEAD",{cwd:e}),{stdout:c}=await I("git rev-parse HEAD",{cwd:e}),{stdout:l}=await I("git rev-parse --show-toplevel",{cwd:e}),u=l.trim(),d=Et.basename(u);return{path:u,branch:o.trim(),commit:c.trim(),isMain:!1,slug:d}}return null}catch{return null}}async getMainWorktree(e){try{let{stdout:r}=await I("git worktree list --porcelain",{cwd:e}),s=r.split(`
1196
+ `):null}catch{return null}}async function vi(n,e,t=100){let r=await DS(n,t),s=r?Pt(e):null;if(s?.historyFingerprint===r)return s;let i=await NS(n,t);return r&&(i.historyFingerprint=r),PS(e,i),i}var ja,Si,is=f(()=>{"use strict";La();P();pe();a(AS,"parseGitLog");a(CS,"isSourceFile");a(NS,"buildMatrix");a(IS,"pairKey");a(ss,"scoreFromSeeds");ja="cochange-index",Si=new Map;a(PS,"saveMatrix");a(Pt,"loadMatrix");a(DS,"recentHistoryFingerprint");a(vi,"indexCoChanges")});function OS(n){return n instanceof os}function ke(n){return OS(n)||n instanceof Error?n.message:typeof n=="string"?n:"Unknown error"}var os,bi,as,Dt=f(()=>{"use strict";os=class extends Error{static{a(this,"PrjctError")}code;isOperational;constructor(e,t="PRJCT_ERROR"){super(e),this.name="PrjctError",this.code=t,this.isOperational=!0,Error.captureStackTrace?.(this,this.constructor)}},bi=class n extends os{static{a(this,"ProjectError")}constructor(e,t="PROJECT_ERROR"){super(e,t),this.name="ProjectError"}static notInitialized(){return new n("Project not initialized. Run p. init first.","PROJECT_NOT_INIT")}static notFound(e){return new n(`Project not found: ${e}`,"PROJECT_NOT_FOUND")}static invalidId(e){return new n(`Invalid project ID: ${e}`,"PROJECT_INVALID_ID")}},as=class n extends os{static{a(this,"AgentError")}constructor(e,t="AGENT_ERROR"){super(e,t),this.name="AgentError"}static notSupported(e){return new n(`Unsupported agent type: ${e}`,"AGENT_NOT_SUPPORTED")}static initFailed(e){return new n(`Agent initialization failed: ${e}`,"AGENT_INIT_FAILED")}};a(OS,"isPrjctError");a(ke,"getErrorMessage")});function Up(n){let e=n.toLowerCase();return e.includes("github")?"github":e.includes("gitlab")?"gitlab":e.includes("bitbucket")?"bitbucket":"other"}function Ma(n){let e=n.trim();if(!e)return{};let t=e.match(/^[^/@]+@([^:/]+):(.+?)(?:\.git)?\/?$/);if(t)return{provider:Up(t[1]),repoSlug:t[2]};try{let r=new URL(e),s=r.pathname.replace(/^\/+/,"").replace(/\.git$/,"").replace(/\/+$/,"");return!r.host||!s?{}:{provider:Up(r.host),repoSlug:s}}catch{return{}}}async function LS(n){try{let{stdout:e}=await G("git",["remote","get-url","origin"],{cwd:n});return e.trim()||void 0}catch{return}}async function jS(n){try{let{stdout:e}=await G("git",["symbolic-ref","--short","refs/remotes/origin/HEAD"],{cwd:n});return e.trim().replace(/^origin\//,"")||void 0}catch{return}}function Sn(n){return typeof n=="string"&&n.length>0?n:void 0}function Hp(n){return typeof n=="number"&&Number.isFinite(n)?n:void 0}function MS(n){return Object.fromEntries(Object.entries(n).filter(([,e])=>e!==void 0))}async function Wp(n){let e=y.getDoc(n,"project")||{},t=Sn(e.repoPath),{provider:r,repoSlug:s}=t?Ma(await LS(t)||""):{},i=t?await jS(t):void 0,o=Array.isArray(e.techStack)?e.techStack.filter(c=>typeof c=="string"):void 0;return MS({provider:r,repoSlug:s,currentBranch:Sn(e.currentBranch),defaultBranch:i,stack:Sn(e.stack),techStack:o&&o.length>0?o:void 0,version:Sn(e.version),commitCount:Hp(e.commitCount),fileCount:Hp(e.fileCount),lastCommit:Sn(e.lastSyncCommit),hasUncommitted:typeof e.hasUncommittedChanges=="boolean"?e.hasUncommittedChanges:void 0,cliVersion:Sn(e.cliVersion),syncedAt:Sn(e.lastSync)})}var Fa=f(()=>{"use strict";P();pe();a(Up,"providerForHost");a(Ma,"parseRemote");a(LS,"gitRemoteUrl");a(jS,"gitDefaultBranch");a(Sn,"str");a(Hp,"num");a(MS,"compact");a(Wp,"buildProjectMeta")});import{execFile as FS}from"node:child_process";import $S from"node:crypto";import{promisify as US}from"node:util";function GS(n,e=WS){let t=Buffer.from(e.replace(/-/g,""),"hex"),s=$S.createHash("sha1").update(t).update(n,"utf8").digest().subarray(0,16);s[6]=s[6]&15|80,s[8]=s[8]&63|128;let i=s.toString("hex");return`${i.slice(0,8)}-${i.slice(8,12)}-${i.slice(12,16)}-${i.slice(16,20)}-${i.slice(20,32)}`}async function BS(n){let e;try{let{stdout:s}=await HS("git",["remote","get-url","origin"],{cwd:n});e=s.trim()||void 0}catch{return null}if(!e)return null;let{provider:t,repoSlug:r}=Ma(e);return!t||!r?null:`${t}:${r}`.toLowerCase()}async function Gp(n){let e=await BS(n);return e?GS(e):null}var HS,WS,Bp=f(()=>{"use strict";Fa();HS=US(FS),WS="6f9b2c1a-3d4e-5f60-8a7b-1c2d3e4f5a6b";a(GS,"uuidv5");a(BS,"repoKey");a(Gp,"deriveProjectId")});var Ha={};q(Ha,{PACKAGE_ROOT:()=>nn,VERSION:()=>tn,getPackageRoot:()=>Ua,getVersion:()=>Ri,resetPackageRoot:()=>XS});import $a from"node:fs";import _i from"node:path";function Ua(){if(sr)return sr;let n=__dirname;for(let e=0;e<5;e++){let t=_i.join(n,"package.json");if($a.existsSync(t))try{if(JSON.parse($a.readFileSync(t,"utf-8")).name==="prjct-cli")return sr=n,n}catch{}n=_i.dirname(n)}return sr=_i.join(__dirname,"..","..",".."),sr}function Ri(){if(vn)return vn;let n="3.40.0";if(n&&/^\d+\.\d+\.\d+/.test(n))return vn=n,vn;try{let e=_i.join(Ua(),"package.json");return vn=JSON.parse($a.readFileSync(e,"utf-8")).version,vn}catch(e){return process.env.PRJCT_DEBUG==="1"&&console.error("Failed to read version from package.json:",v(e)),"0.0.0"}}function XS(n){sr=n,vn=null}var vn,sr,tn,nn,Ot=f(()=>{"use strict";ee();vn=null,sr=null;a(Ua,"getPackageRoot");a(Ri,"getVersion");a(XS,"resetPackageRoot");tn=Ri(),nn=Ua()});async function xi(n){try{let{stdout:e}=await I(n,{timeout:5e3});return{success:!0,output:e.trim()}}catch{return{success:!1,output:""}}}async function qS(){let n=await xi("gh api user --jq .login");return n.success&&n.output||(n=await xi("git config --global github.user"),n.success&&n.output)?n.output:null}async function VS(){let n=await xi("git config user.name");return n.success&&n.output?n.output:null}async function JS(){let n=await xi("git config user.email");return n.success&&n.output?n.output:null}async function ir(){let[n,e,t]=await Promise.all([qS(),VS(),JS()]);return{github:n,email:t,name:e||n||"Unknown"}}var Ai=f(()=>{"use strict";pe();a(xi,"execCommand");a(qS,"detectGitHubUsername");a(VS,"detectGitName");a(JS,"detectGitEmail");a(ir,"detect")});var Xa={};q(Xa,{worktreeService:()=>KS});import Ga from"node:fs/promises";import Et from"node:path";var Xp,Ba,KS,qa=f(()=>{"use strict";pe();te();Xp=".worktrees",Ba=class{static{a(this,"WorktreeService")}async create(e,t,r={}){let s=await this.getMainWorktree(e),i=Et.join(s,Xp,t),o=r.branch||`feat/${t}`;await Ga.mkdir(Et.join(s,Xp),{recursive:!0});let c=r.baseBranch?` ${r.baseBranch}`:"";await I(`git worktree add "${i}" -b "${o}"${c}`,{cwd:s});let{stdout:l}=await I("git rev-parse HEAD",{cwd:i});return{path:i,branch:o,commit:l.trim(),isMain:!1,slug:t}}async remove(e,t=!1){let r=await this.getMainWorktree(e),s;if(t)try{let{stdout:i}=await I("git rev-parse --abbrev-ref HEAD",{cwd:e});s=i.trim()}catch{}if(await I(`git worktree remove "${e}" --force`,{cwd:r}),t&&s&&s!=="main"&&s!=="master")try{await I(`git branch -D "${s}"`,{cwd:r})}catch{}}async list(e){let t=await this.getMainWorktree(e),{stdout:r}=await I("git worktree list --porcelain",{cwd:t});return this.parsePorcelainOutput(r,t)}async detect(e){try{let{stdout:t}=await I("git rev-parse --git-common-dir",{cwd:e}),{stdout:r}=await I("git rev-parse --git-dir",{cwd:e}),s=Et.resolve(e,t.trim()),i=Et.resolve(e,r.trim());if(s!==i){let{stdout:o}=await I("git rev-parse --abbrev-ref HEAD",{cwd:e}),{stdout:c}=await I("git rev-parse HEAD",{cwd:e}),{stdout:l}=await I("git rev-parse --show-toplevel",{cwd:e}),u=l.trim(),d=Et.basename(u);return{path:u,branch:o.trim(),commit:c.trim(),isMain:!1,slug:d}}return null}catch{return null}}async getMainWorktree(e){try{let{stdout:r}=await I("git worktree list --porcelain",{cwd:e}),s=r.split(`
1197
1197
  `)[0];if(s?.startsWith("worktree "))return s.replace("worktree ","").trim()}catch{}let{stdout:t}=await I("git rev-parse --show-toplevel",{cwd:e});return t.trim()}async setup(e,t){let r=Et.join(t,".env");await _(r)&&await Ga.copyFile(r,Et.join(e,".env"));let s=Et.join(t,".prjct"),i=Et.join(e,".prjct");await _(s)&&!await _(i)&&await Ga.symlink(s,i,"dir")}async teardown(e){}async clean(e){let t=await this.list(e),r=[],s=await this.getMainWorktree(e);await I("git worktree prune",{cwd:s});for(let i of t)i.isMain||await _(i.path)||r.push(i.slug);return r}parsePorcelainOutput(e,t){let r=[],s=e.trim().split(`
1198
1198
 
1199
1199
  `);for(let i of s){if(!i.trim())continue;let o=i.trim().split(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prjct-cli",
3
- "version": "3.39.0",
3
+ "version": "3.40.0",
4
4
  "description": "Project memory and workflow context for AI coding agents.",
5
5
  "main": "dist/bin/prjct.mjs",
6
6
  "bin": {