prjct-cli 2.19.8 → 2.20.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.
@@ -549,8 +549,8 @@ CREATE TABLE velocity_sprints (
549
549
  END { for (f in files) print files[f], lastmod[f], f }
550
550
  '`,{cwd:r,maxBuffer:10485760}),s=Math.floor(Date.now()/1e3),n=e.trim().split(`
551
551
  `).filter(Boolean);for(let i of n){let o=i.match(/^(\d+)\s+(\d+)\s+(.+)$/);if(o){let a=parseInt(o[1],10),u=parseInt(o[2],10),p=o[3],m=Math.floor((s-u)/86400);t.set(p,{commits:a,daysAgo:m})}}}catch{}return t}function yo(r,t,e,s){let n=[],i=0,o=0,a=0,u=0,p=0,m=r.toLowerCase(),d=m.split("/").join(" ").split(/[^a-z0-9]+/);for(let N of t){m.includes(N)&&(i+=.3,n.push(`keyword:${N}`));for(let dt of d)if(dt.includes(N)||N.includes(dt)){i+=.15;break}}i=Math.min(1,i);for(let[N,dt]of Object.entries(cn))for(let Hn of dt)if(m.includes(Hn)&&t.some(Vt=>dt.includes(Vt)||Vt.includes(N)||N.includes(Vt))){o+=.4,n.push(`domain:${N}`);break}o=Math.min(1,o);let f=e.get(r);f&&(f.daysAgo<=1?(a=1,n.push("recent:1d")):f.daysAgo<=3?(a=.8,n.push("recent:3d")):f.daysAgo<=7?(a=.6,n.push("recent:1w")):f.daysAgo<=30&&(a=.3,n.push("recent:1m")),f.commits>=5&&(a=Math.min(1,a+.2)));let y=Ht.basename(r).toLowerCase();if((y.includes("index")||y.includes("main")||y.includes("app")||y.includes("entry"))&&(u=.5,n.push("import:0")),(m.includes("/core/")||m.includes("/shared/")||m.includes("/lib/"))&&(u=Math.max(u,.3),n.some(N=>N.startsWith("import:"))||n.push("import:1")),s){let N=s.get(r);N!==void 0&&(p=(N+1)/2,N>0?n.push("history:boosted"):N<0&&n.push("history:penalized"))}let et=s&&s.size>0?i*.54+o*.18+a*.13+u*.05+p*.1:i*.6+o*.2+a*.15+u*.05;return{path:r,score:Math.min(1,et),reasons:[...new Set(n)]}}function To(r){let t=r.toLowerCase();return t.includes(".test.")||t.includes(".spec.")||t.includes("__tests__")||t.includes("__mocks__")||t.includes("/tests/")||t.includes("/test/")||t.endsWith("_test.go")||t.endsWith("_test.py")}var Be=k(()=>{"use strict";V();rt();dn();c(qt,"findRelevantFiles");c(go,"extractKeywords");c(fo,"getAllCodeFiles");c(ho,"getGitRecency");c(yo,"scoreFile");c(To,"isTestFile")});var qe,En,Sn=k(()=>{"use strict";Tt();Wt();M();qe=class{static{c(this,"MemoryService")}async log(t,e,s,n){try{let i=await H.getProjectId(t);if(!i)return;T.appendEvent(i,`memory.${e}`,{...s,author:n})}catch(i){console.error(`Memory log error: ${i instanceof Error?i.message:String(i)}`)}}async getRecent(t,e=100){try{let s=await H.getProjectId(t);return s?T.query(s,"SELECT type, data, timestamp FROM events WHERE type LIKE 'memory.%' ORDER BY id DESC LIMIT ?",e).reverse().map(i=>{let o=JSON.parse(i.data),{author:a,...u}=o;return{timestamp:i.timestamp,action:i.type.replace("memory.",""),data:u,author:a}}):[]}catch(s){return console.error(`Memory read error: ${s instanceof Error?s.message:String(s)}`),[]}}async search(t,e,s=50){let n=await this.getRecent(t,1e3),i=e.toLowerCase();return n.filter(o=>{let a=o.action.toLowerCase().includes(i),u=JSON.stringify(o.data).toLowerCase().includes(i);return a||u}).slice(-s)}async getByAction(t,e,s=50){try{let n=await H.getProjectId(t);return n?T.query(n,"SELECT type, data, timestamp FROM events WHERE type = ? ORDER BY id DESC LIMIT ?",`memory.${e}`,s).reverse().map(o=>{let a=JSON.parse(o.data),{author:u,...p}=a;return{timestamp:o.timestamp,action:o.type.replace("memory.",""),data:p,author:u}}):[]}catch(n){return console.error(`Memory read error: ${n instanceof Error?n.message:String(n)}`),[]}}async clear(t){try{let e=await H.getProjectId(t);if(!e)return;T.run(e,"DELETE FROM events WHERE type LIKE 'memory.%'")}catch(e){console.error(`Memory clear error: ${e instanceof Error?e.message:String(e)}`)}}async getRecentEvents(t,e=100){try{return T.query(t,"SELECT type, data, timestamp FROM events WHERE type LIKE 'memory.%' ORDER BY id DESC LIMIT ?",e).reverse().map(n=>{let i=JSON.parse(n.data);return{timestamp:n.timestamp,action:n.type.replace("memory.",""),...i}})}catch(s){return console.error(`Memory read error: ${s instanceof Error?s.message:String(s)}`),[]}}async capEntries(t){try{let s=T.get(t,"SELECT COUNT(*) as cnt FROM events WHERE type LIKE 'memory.%'")?.cnt??0;if(s<=wt.MEMORY_MAX_ENTRIES)return 0;let n=s-wt.MEMORY_MAX_ENTRIES,i=T.query(t,"SELECT id, type, data, timestamp FROM events WHERE type LIKE 'memory.%' ORDER BY id ASC LIMIT ?",n);ot.archiveMany(t,i.map((a,u)=>({entityType:"memory_entry",entityId:`memory-${a.timestamp||u}`,entityData:{type:a.type,data:JSON.parse(a.data),timestamp:a.timestamp},summary:a.type.replace("memory.",""),reason:"overflow"})));let o=i[i.length-1]?.id;return o!==void 0&&T.run(t,"DELETE FROM events WHERE type LIKE 'memory.%' AND id <= ?",o),n}catch(e){return console.error(`Memory cap error: ${e instanceof Error?e.message:String(e)}`),0}}},En=new qe});var wn,Ge,Ye,op,bn=k(()=>{"use strict";wn="memory.",Ge="remember.",Ye=`${wn}${Ge}`,op=`${wn}task.tagged`});function vn(r,t){try{return JSON.parse(r)}catch{return t}}function Lo(r){let t=r.type.slice(Ye.length),e=vn(r.data,{});return{id:`mem_${r.id}`,type:t,content:e.content??"",tags:e.tags??{},rememberedAt:r.timestamp,source:e.source,provenance:e.provenance??"declared"}}function Oo(r){let t=r.data?vn(r.data,{}):{},e=t.tags??{};return r.type&&(e.type=r.type),{id:`ship_${r.id}`,type:"shipped",content:r.name,tags:e,rememberedAt:r.shipped_at,source:t.taskId,provenance:"extracted"}}function jo(r,t){let e=t.toLowerCase();if(r.content.toLowerCase().includes(e))return!0;for(let s of Object.values(r.tags))if(s.toLowerCase().includes(e))return!0;return!1}function Mo(r,t){for(let[e,s]of Object.entries(t))if(r.tags[e]!==s)return!1;return!0}function Fo(r){let t=new Set,e=[];for(let s of r){let n=s.tags.key;if(!n){e.push(s);continue}let i=`${s.type}::${n}`;t.has(i)||(t.add(i),e.push(s))}return e}function bt(r){if(r.length===0)return"> No matching memory entries.";let t=new Map;for(let a of r){let u=t.get(a.type)??[];u.push(a),t.set(a.type,u)}let e=["decision","learning","anti-pattern","gotcha","pattern","fact","inbox","todo","idea","insight","question","source","person","shipped"],s=[],n={declared:"DECL",extracted:"EXTR",inferred:"INFR",ambiguous:"AMBG"},i=c((a,u)=>{if(u.length!==0){s.push(`### ${a.toUpperCase()}`);for(let p of u){let m=Object.entries(p.tags).map(([y,j])=>`${y}=${j}`).join(" "),d=m?` _(${m})_`:"",f=n[p.provenance];s.push(`- \`${f}\` [${p.id}] ${p.content}${d}`)}s.push("")}},"renderGroup"),o=new Set;for(let a of e){let u=t.get(a);!u||u.length===0||(i(a,u),o.add(a))}for(let[a,u]of t)o.has(a)||i(a,u);return s.join(`
552
- `).trim()}var _n,No,Io,Do,O,lt=k(()=>{"use strict";Sn();M();bn();_n=["fact","decision","learning","gotcha","pattern","anti-pattern","shipped","inbox","todo","idea","insight","question","source","person","spec"],No=25,Io=4,Do=100;c(vn,"safeJson");c(Lo,"rowToEntry");c(Oo,"shippedRowToEntry");c(jo,"matchesTopic");c(Mo,"matchesTags");c(Fo,"dedupeLatestByKey");O={async remember(r,t){await En.log(r,`${Ge}${t.type}`,{content:t.content,tags:t.tags??{},source:t.source,provenance:t.provenance??"declared"});try{let{default:e}=await Promise.resolve().then(()=>(Tt(),gr)),n=(await e.readConfig(r))?.projectId;if(!n)return;let{publishCRUD:i}=await Promise.resolve().then(()=>(St(),Cr)),o=t.tags?.spec_id??t.tags?.task_id??t.tags?.id??t.source??`mem-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;await i({projectId:n,entityType:"memories",entityId:o,eventType:"upsert",data:{id:o,type:t.type,content:t.content,tags:t.tags??{},source:t.source??null,provenance:t.provenance??"declared",rememberedAt:new Date().toISOString()}})}catch{}},recall(r,t={}){let e=t.limit??No,s=Math.max(e*Io,Do),n=T.query(r,"SELECT id, type, data, timestamp FROM events WHERE type LIKE ? ORDER BY id DESC LIMIT ?",`${Ye}%`,s),i=T.query(r,"SELECT id, name, type, shipped_at, data FROM shipped_features ORDER BY shipped_at DESC LIMIT ?",s),o=[...n.map(Lo),...i.map(Oo)];if(t.types&&t.types.length>0){let a=new Set(t.types);o=o.filter(u=>a.has(u.type))}return t.tags&&(o=o.filter(a=>Mo(a,t.tags??{}))),t.topic&&(o=o.filter(a=>jo(a,t.topic))),o.sort((a,u)=>u.rememberedAt.localeCompare(a.rememberedAt)),t.dedupeByKey!==!1&&(o=Fo(o)),o.slice(0,e)},similar(r,t,e=10){let s=t.toLowerCase().split(/[^a-z0-9]+/).filter(o=>o.length>3);return s.length===0?[]:O.recall(r,{limit:200}).map(o=>{let a=`${o.content} ${Object.values(o.tags).join(" ")}`.toLowerCase(),u=s.reduce((p,m)=>a.includes(m)?p+1:p,0);return{entry:o,hits:u}}).filter(o=>o.hits>0).sort((o,a)=>a.hits-o.hits).slice(0,e).map(o=>o.entry)}};c(bt,"formatMemoryMd")});function Dn(r){return[...r].sort((t,e)=>{let s=In[t.section]-In[e.section];return s!==0?s:Nn[t.priority]-Nn[e.priority]})}var Nn,In,Ln=k(()=>{"use strict";Nn={critical:0,high:1,medium:2,low:3},In={active:0,previously_active:1,backlog:2};c(Dn,"sortBySectionAndPriority")});var ze,_t,Ke=k(()=>{"use strict";Et();Ut();Ln();A();Wt();$e();ze=class extends at{static{c(this,"QueueStorage")}constructor(){super("queue.json",wr)}getDefault(){return{tasks:[],lastUpdated:""}}getEventType(t){return`queue.${t}d`}async getTasks(t){return(await this.read(t)).tasks}async getActiveTasks(t){return(await this.read(t)).tasks.filter(s=>s.section==="active"&&!s.completed)}async getBacklog(t){return(await this.read(t)).tasks.filter(s=>s.section==="backlog"&&!s.completed)}async getNextTask(t){let e=await this.getActiveTasks(t);return Dn(e)[0]||null}async addTask(t,e){let s={...e,id:q(),createdAt:g(),completed:!1};return await this.update(t,n=>({tasks:[...n.tasks,s],lastUpdated:g()})),await this.publishEvent(t,"queue.task_added",{taskId:s.id,description:s.description,priority:s.priority,section:s.section}),s}async addTasks(t,e){let s=g(),n=e.map(i=>({...i,id:q(),createdAt:s,completed:!1}));return await this.update(t,i=>({tasks:[...i.tasks,...n],lastUpdated:s})),await this.publishEvent(t,"queue.tasks_added",{count:n.length,tasks:n.map(i=>({id:i.id,description:i.description}))}),n}async removeTask(t,e){await this.update(t,s=>({tasks:s.tasks.filter(n=>n.id!==e),lastUpdated:g()})),await this.publishEvent(t,"queue.task_removed",{taskId:e})}async deleteByFeatureId(t,e){let s=0;return await this.update(t,n=>{let i=n.tasks.length,o=n.tasks.filter(a=>a.featureId!==e);return s=i-o.length,{tasks:o,lastUpdated:g()}}),s>0&&await this.publishEvent(t,"queue.tasks_removed_by_feature",{featureId:e,count:s}),s}async completeTask(t,e){let s=null;if(await this.update(t,n=>({tasks:n.tasks.map(o=>o.id===e?(s={...o,completed:!0,completedAt:g()},s):o),lastUpdated:g()})),s){let n=s;await this.publishEvent(t,"queue.task_completed",{taskId:e,description:n.description,completedAt:n.completedAt})}return s}async moveToSection(t,e,s){await this.update(t,n=>({tasks:n.tasks.map(i=>i.id===e?{...i,section:s}:i),lastUpdated:g()}))}async setPriority(t,e,s){await this.update(t,n=>({tasks:n.tasks.map(i=>i.id===e?{...i,priority:s}:i),lastUpdated:g()}))}async getTask(t,e){return(await this.read(t)).tasks.find(n=>n.id===e)||null}async updateTask(t,e,s){let n=null;return await this.update(t,i=>({tasks:i.tasks.map(o=>o.id===e?(n={...o,...s},n):o),lastUpdated:g()})),n&&await this.publishEvent(t,"queue.task_updated",{taskId:e}),n}async clearCompleted(t){let s=(await this.read(t)).tasks.filter(n=>n.completed).length;return await this.update(t,n=>({tasks:n.tasks.filter(i=>!i.completed),lastUpdated:g()})),s}async removeStaleCompleted(t){let e=await this.read(t),s=ps(wt.QUEUE_COMPLETED_DAYS),n=e.tasks.filter(o=>o.completed&&o.completedAt&&new Date(o.completedAt)<s);if(n.length===0)return 0;ot.archiveMany(t,n.map(o=>({entityType:"queue_task",entityId:o.id,entityData:o,summary:o.description,reason:"age"})));let i=new Set(n.map(o=>o.id));return await this.update(t,o=>({tasks:o.tasks.filter(a=>!i.has(a.id)),lastUpdated:g()})),await this.publishEvent(t,"queue.stale_removed",{count:n.length}),n.length}},_t=new ze});import{z as b}from"zod";var pt,Ze,Qe,Xo,Y,Yt=k(()=>{"use strict";pt=["draft","reviewed","in_progress","shipped","archived"],Ze=["strategic","architecture","design"],Qe=b.object({verdict:b.enum(["pass","fail"]),notes:b.string(),ts:b.string()}),Xo=b.object({risk:b.string().min(1),mitigation:b.string().min(1)}),Y=b.object({goal:b.string().min(1),eli10:b.string().default(""),stakes:b.string().default(""),acceptance_criteria:b.array(b.string().min(1)).default([]),scope:b.array(b.string()).default([]),out_of_scope:b.array(b.string()).default([]),risks:b.array(Xo).default([]),test_plan:b.array(b.string()).default([]),reviews:b.object({strategic:Qe.optional(),architecture:Qe.optional(),design:Qe.optional()}).optional(),linked_tasks:b.array(b.string()).default([]),notes:b.string().default(""),tasks_created_at:b.string().nullable().default(null)})});var ts,v,Jt=k(()=>{"use strict";Et();Yt();A();M();ts=class{static{c(this,"SpecStorage")}create(t,e){let s=q(),n=g(),i=Y.parse(e.content);return T.run(t,`INSERT INTO specs (id, title, status, content, tags, created_at, updated_at)
553
- VALUES (?, ?, 'draft', ?, ?, ?, ?)`,s,e.title,JSON.stringify(i),e.tags?JSON.stringify(e.tags):null,n,n),{id:s,title:e.title,status:"draft",content:i,tags:e.tags??{},createdAt:n,updatedAt:n,shippedAt:null,shippedPr:null,shippedSha:null,archivedAt:null}}get(t,e){let s=T.get(t,"SELECT * FROM specs WHERE id = ?",e);return s?this.rowToSpec(s):null}list(t,e={}){let s="SELECT * FROM specs WHERE 1=1",n=[];return e.status&&(s+=" AND status = ?",n.push(e.status)),!e.includeArchived&&!e.status&&(s+=" AND status != 'archived'"),s+=" ORDER BY created_at DESC",T.query(t,s,...n).map(o=>this.rowToSpec(o))}search(t,e){let s=`%${e}%`;return T.query(t,"SELECT * FROM specs WHERE title LIKE ? OR content LIKE ? ORDER BY created_at DESC",s,s).map(i=>this.rowToSpec(i))}updateContent(t,e,s){let n=Y.parse(s),i=g();return T.run(t,"UPDATE specs SET content = ?, updated_at = ? WHERE id = ?",JSON.stringify(n),i,e),this.get(t,e)}casUpdate(t,e,s,n){let i=Y.parse(s),o=g();return T.run(t,"UPDATE specs SET content = ?, updated_at = ? WHERE id = ? AND updated_at = ?",JSON.stringify(i),o,e,n).changes===1}setStatus(t,e,s){if(!pt.includes(s))throw new Error(`invalid spec status: ${s}`);let n=g(),i=[],o=[s,n];s==="shipped"&&(i.push("shipped_at = ?"),o.push(n)),s==="archived"&&(i.push("archived_at = ?"),o.push(n));let a=["status = ?","updated_at = ?",...i].join(", ");return o.push(e),T.run(t,`UPDATE specs SET ${a} WHERE id = ?`,...o),this.get(t,e)}setShippedPr(t,e,s){return T.run(t,"UPDATE specs SET shipped_pr = ?, updated_at = ? WHERE id = ?",s,g(),e),this.get(t,e)}setShippedSha(t,e,s){return T.run(t,"UPDATE specs SET shipped_sha = ?, updated_at = ? WHERE id = ?",s,g(),e),this.get(t,e)}linkTask(t,e,s){let n=this.get(t,e);if(!n)return null;if(n.content.linked_tasks.includes(s))return n;let i={...n.content,linked_tasks:[...n.content.linked_tasks,s]};return this.updateContent(t,e,i)}delete(t,e){return this.get(t,e)?(T.run(t,"DELETE FROM specs WHERE id = ?",e),!0):!1}count(t){let e=T.query(t,"SELECT status, COUNT(*) AS n FROM specs GROUP BY status"),s={total:0,draft:0,shipped:0};for(let n of e)s.total+=n.n,n.status==="draft"&&(s.draft=n.n),n.status==="shipped"&&(s.shipped=n.n);return s}rowToSpec(t){return{id:t.id,title:t.title,status:pt.includes(t.status)?t.status:"draft",content:Y.parse(JSON.parse(t.content)),tags:t.tags?JSON.parse(t.tags):{},createdAt:t.created_at,updatedAt:t.updated_at,shippedAt:t.shipped_at,shippedPr:t.shipped_pr,shippedSha:t.shipped_sha,archivedAt:t.archived_at}}},v=new ts});var Mn={};K(Mn,{inferSpecContext:()=>Bo,warnNoContextMatch:()=>Go});async function Bo(r,t,e){let[s,n]=await Promise.all([qt(r,e,{maxFiles:jn*4,minScore:Wo}).catch(()=>({files:[]})),Promise.resolve(O.recall(t,{topic:r,limit:$o})).catch(()=>[])]),i=Ho(s.files.map(u=>u.path),jn);return i.length===0&&n.length===0?{notesBlock:"",paths:[],memoryHits:0,empty:!0}:{notesBlock:qo(r,i,n),paths:i,memoryHits:n.length,empty:!1}}function Ho(r,t){let e=new Set,s=[];for(let n of r){let i=n.split("/").slice(0,2).join("/");if(!e.has(i)&&(e.add(i),s.push(n),s.length>=t))break}return s}function qo(r,t,e){let s=[];if(s.push("<!-- auto-context:tentative -->"),s.push("## Existing context (auto-inferred)"),s.push(""),s.push(`_Inferred from title "${r}". Validate before audit \u2014 entries tagged tentative._`),s.push(""),t.length>0){s.push("### Likely paths");for(let n of t)s.push(`- \`${n}\``);s.push("")}if(e.length>0){s.push("### Relevant prior memory");for(let n of e){let i=n.content.length>140?`${n.content.slice(0,137)}\u2026`:n.content,o=Object.entries(n.tags).map(([a,u])=>`${a}:${u}`).join(" ");s.push(`- **${n.type}**${o?` _(${o})_`:""} \u2014 ${i}`)}s.push("")}return s.push("<!-- /auto-context -->"),s.join(`
552
+ `).trim()}var _n,No,Io,Do,O,lt=k(()=>{"use strict";Sn();M();bn();_n=["fact","decision","learning","gotcha","pattern","anti-pattern","shipped","inbox","todo","idea","insight","question","source","person","spec"],No=25,Io=4,Do=100;c(vn,"safeJson");c(Lo,"rowToEntry");c(Oo,"shippedRowToEntry");c(jo,"matchesTopic");c(Mo,"matchesTags");c(Fo,"dedupeLatestByKey");O={async remember(r,t){await En.log(r,`${Ge}${t.type}`,{content:t.content,tags:t.tags??{},source:t.source,provenance:t.provenance??"declared"});try{let{default:e}=await Promise.resolve().then(()=>(Tt(),gr)),n=(await e.readConfig(r))?.projectId;if(!n)return;let{publishCRUD:i}=await Promise.resolve().then(()=>(St(),Cr)),o=t.tags?.spec_id??t.tags?.task_id??t.tags?.id??t.source??`mem-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;await i({projectId:n,entityType:"memories",entityId:o,eventType:"upsert",data:{id:o,type:t.type,content:t.content,tags:t.tags??{},source:t.source??null,provenance:t.provenance??"declared",rememberedAt:new Date().toISOString()}})}catch{}},recall(r,t={}){let e=t.limit??No,s=Math.max(e*Io,Do),n=T.query(r,"SELECT id, type, data, timestamp FROM events WHERE type LIKE ? ORDER BY id DESC LIMIT ?",`${Ye}%`,s),i=T.query(r,"SELECT id, name, type, shipped_at, data FROM shipped_features ORDER BY shipped_at DESC LIMIT ?",s),o=[...n.map(Lo),...i.map(Oo)];if(t.types&&t.types.length>0){let a=new Set(t.types);o=o.filter(u=>a.has(u.type))}return t.tags&&(o=o.filter(a=>Mo(a,t.tags??{}))),t.topic&&(o=o.filter(a=>jo(a,t.topic))),o.sort((a,u)=>u.rememberedAt.localeCompare(a.rememberedAt)),t.dedupeByKey!==!1&&(o=Fo(o)),o.slice(0,e)},similar(r,t,e=10){let s=t.toLowerCase().split(/[^a-z0-9]+/).filter(o=>o.length>3);return s.length===0?[]:O.recall(r,{limit:200}).map(o=>{let a=`${o.content} ${Object.values(o.tags).join(" ")}`.toLowerCase(),u=s.reduce((p,m)=>a.includes(m)?p+1:p,0);return{entry:o,hits:u}}).filter(o=>o.hits>0).sort((o,a)=>a.hits-o.hits).slice(0,e).map(o=>o.entry)}};c(bt,"formatMemoryMd")});function Dn(r){return[...r].sort((t,e)=>{let s=In[t.section]-In[e.section];return s!==0?s:Nn[t.priority]-Nn[e.priority]})}var Nn,In,Ln=k(()=>{"use strict";Nn={critical:0,high:1,medium:2,low:3},In={active:0,previously_active:1,backlog:2};c(Dn,"sortBySectionAndPriority")});var ze,_t,Ke=k(()=>{"use strict";Et();Ut();Ln();A();Wt();$e();ze=class extends at{static{c(this,"QueueStorage")}constructor(){super("queue.json",wr)}getDefault(){return{tasks:[],lastUpdated:""}}getEventType(t){return`queue.${t}d`}async getTasks(t){return(await this.read(t)).tasks}async getActiveTasks(t){return(await this.read(t)).tasks.filter(s=>s.section==="active"&&!s.completed)}async getBacklog(t){return(await this.read(t)).tasks.filter(s=>s.section==="backlog"&&!s.completed)}async getNextTask(t){let e=await this.getActiveTasks(t);return Dn(e)[0]||null}async addTask(t,e){let s={...e,id:q(),createdAt:g(),completed:!1};return await this.update(t,n=>({tasks:[...n.tasks,s],lastUpdated:g()})),await this.publishEvent(t,"queue.task_added",{taskId:s.id,description:s.description,priority:s.priority,section:s.section}),s}async addTasks(t,e){let s=g(),n=e.map(i=>({...i,id:q(),createdAt:s,completed:!1}));return await this.update(t,i=>({tasks:[...i.tasks,...n],lastUpdated:s})),await this.publishEvent(t,"queue.tasks_added",{count:n.length,tasks:n.map(i=>({id:i.id,description:i.description}))}),n}async removeTask(t,e){await this.update(t,s=>({tasks:s.tasks.filter(n=>n.id!==e),lastUpdated:g()})),await this.publishEvent(t,"queue.task_removed",{taskId:e})}async deleteByFeatureId(t,e){let s=0;return await this.update(t,n=>{let i=n.tasks.length,o=n.tasks.filter(a=>a.featureId!==e);return s=i-o.length,{tasks:o,lastUpdated:g()}}),s>0&&await this.publishEvent(t,"queue.tasks_removed_by_feature",{featureId:e,count:s}),s}async completeTask(t,e){let s=null;if(await this.update(t,n=>({tasks:n.tasks.map(o=>o.id===e?(s={...o,completed:!0,completedAt:g()},s):o),lastUpdated:g()})),s){let n=s;await this.publishEvent(t,"queue.task_completed",{taskId:e,description:n.description,completedAt:n.completedAt})}return s}async moveToSection(t,e,s){await this.update(t,n=>({tasks:n.tasks.map(i=>i.id===e?{...i,section:s}:i),lastUpdated:g()}))}async setPriority(t,e,s){await this.update(t,n=>({tasks:n.tasks.map(i=>i.id===e?{...i,priority:s}:i),lastUpdated:g()}))}async getTask(t,e){return(await this.read(t)).tasks.find(n=>n.id===e)||null}async updateTask(t,e,s){let n=null;return await this.update(t,i=>({tasks:i.tasks.map(o=>o.id===e?(n={...o,...s},n):o),lastUpdated:g()})),n&&await this.publishEvent(t,"queue.task_updated",{taskId:e}),n}async clearCompleted(t){let s=(await this.read(t)).tasks.filter(n=>n.completed).length;return await this.update(t,n=>({tasks:n.tasks.filter(i=>!i.completed),lastUpdated:g()})),s}async removeStaleCompleted(t){let e=await this.read(t),s=ps(wt.QUEUE_COMPLETED_DAYS),n=e.tasks.filter(o=>o.completed&&o.completedAt&&new Date(o.completedAt)<s);if(n.length===0)return 0;ot.archiveMany(t,n.map(o=>({entityType:"queue_task",entityId:o.id,entityData:o,summary:o.description,reason:"age"})));let i=new Set(n.map(o=>o.id));return await this.update(t,o=>({tasks:o.tasks.filter(a=>!i.has(a.id)),lastUpdated:g()})),await this.publishEvent(t,"queue.stale_removed",{count:n.length}),n.length}},_t=new ze});import{z as b}from"zod";var pt,Ze,Qe,Xo,Y,Yt=k(()=>{"use strict";pt=["draft","reviewed","in_progress","shipped","archived"],Ze=["strategic","architecture","design"],Qe=b.object({verdict:b.enum(["pass","fail"]),notes:b.string(),ts:b.string()}),Xo=b.object({risk:b.string().min(1),mitigation:b.string().min(1)}),Y=b.object({goal:b.string().min(1),eli10:b.string().default(""),stakes:b.string().default(""),acceptance_criteria:b.array(b.string().min(1)).default([]),scope:b.array(b.string()).default([]),out_of_scope:b.array(b.string()).default([]),risks:b.array(Xo).default([]),test_plan:b.array(b.string()).default([]),reviews:b.object({strategic:Qe.optional(),architecture:Qe.optional(),design:Qe.optional()}).optional(),linked_tasks:b.array(b.string()).default([]),notes:b.string().default(""),tasks_created_at:b.string().nullable().default(null)})});var ts,v,Jt=k(()=>{"use strict";Et();Yt();A();M();ts=class{static{c(this,"SpecStorage")}nextUpdatedAt(t,e){let s=g(),i=T.get(t,"SELECT updated_at FROM specs WHERE id = ?",e)?.updated_at;return!i||s>i?s:new Date(new Date(i).getTime()+1).toISOString()}create(t,e){let s=q(),n=g(),i=Y.parse(e.content);return T.run(t,`INSERT INTO specs (id, title, status, content, tags, created_at, updated_at)
553
+ VALUES (?, ?, 'draft', ?, ?, ?, ?)`,s,e.title,JSON.stringify(i),e.tags?JSON.stringify(e.tags):null,n,n),{id:s,title:e.title,status:"draft",content:i,tags:e.tags??{},createdAt:n,updatedAt:n,shippedAt:null,shippedPr:null,shippedSha:null,archivedAt:null}}get(t,e){let s=T.get(t,"SELECT * FROM specs WHERE id = ?",e);return s?this.rowToSpec(s):null}list(t,e={}){let s="SELECT * FROM specs WHERE 1=1",n=[];return e.status&&(s+=" AND status = ?",n.push(e.status)),!e.includeArchived&&!e.status&&(s+=" AND status != 'archived'"),s+=" ORDER BY created_at DESC",T.query(t,s,...n).map(o=>this.rowToSpec(o))}search(t,e){let s=`%${e}%`;return T.query(t,"SELECT * FROM specs WHERE title LIKE ? OR content LIKE ? ORDER BY created_at DESC",s,s).map(i=>this.rowToSpec(i))}updateContent(t,e,s){let n=Y.parse(s),i=this.nextUpdatedAt(t,e);return T.run(t,"UPDATE specs SET content = ?, updated_at = ? WHERE id = ?",JSON.stringify(n),i,e),this.get(t,e)}casUpdate(t,e,s,n){let i=Y.parse(s),o=this.nextUpdatedAt(t,e);return T.run(t,"UPDATE specs SET content = ?, updated_at = ? WHERE id = ? AND updated_at = ?",JSON.stringify(i),o,e,n).changes===1}setStatus(t,e,s){if(!pt.includes(s))throw new Error(`invalid spec status: ${s}`);let n=this.nextUpdatedAt(t,e),i=[],o=[s,n];s==="shipped"&&(i.push("shipped_at = ?"),o.push(n)),s==="archived"&&(i.push("archived_at = ?"),o.push(n));let a=["status = ?","updated_at = ?",...i].join(", ");return o.push(e),T.run(t,`UPDATE specs SET ${a} WHERE id = ?`,...o),this.get(t,e)}setShippedPr(t,e,s){return T.run(t,"UPDATE specs SET shipped_pr = ?, updated_at = ? WHERE id = ?",s,this.nextUpdatedAt(t,e),e),this.get(t,e)}setShippedSha(t,e,s){return T.run(t,"UPDATE specs SET shipped_sha = ?, updated_at = ? WHERE id = ?",s,this.nextUpdatedAt(t,e),e),this.get(t,e)}linkTask(t,e,s){let n=this.get(t,e);if(!n)return null;if(n.content.linked_tasks.includes(s))return n;let i={...n.content,linked_tasks:[...n.content.linked_tasks,s]};return this.updateContent(t,e,i)}delete(t,e){return this.get(t,e)?(T.run(t,"DELETE FROM specs WHERE id = ?",e),!0):!1}count(t){let e=T.query(t,"SELECT status, COUNT(*) AS n FROM specs GROUP BY status"),s={total:0,draft:0,shipped:0};for(let n of e)s.total+=n.n,n.status==="draft"&&(s.draft=n.n),n.status==="shipped"&&(s.shipped=n.n);return s}rowToSpec(t){return{id:t.id,title:t.title,status:pt.includes(t.status)?t.status:"draft",content:Y.parse(JSON.parse(t.content)),tags:t.tags?JSON.parse(t.tags):{},createdAt:t.created_at,updatedAt:t.updated_at,shippedAt:t.shipped_at,shippedPr:t.shipped_pr,shippedSha:t.shipped_sha,archivedAt:t.archived_at}}},v=new ts});var Mn={};K(Mn,{inferSpecContext:()=>Bo,warnNoContextMatch:()=>Go});async function Bo(r,t,e){let[s,n]=await Promise.all([qt(r,e,{maxFiles:jn*4,minScore:Wo}).catch(()=>({files:[]})),Promise.resolve(O.recall(t,{topic:r,limit:$o})).catch(()=>[])]),i=Ho(s.files.map(u=>u.path),jn);return i.length===0&&n.length===0?{notesBlock:"",paths:[],memoryHits:0,empty:!0}:{notesBlock:qo(r,i,n),paths:i,memoryHits:n.length,empty:!1}}function Ho(r,t){let e=new Set,s=[];for(let n of r){let i=n.split("/").slice(0,2).join("/");if(!e.has(i)&&(e.add(i),s.push(n),s.length>=t))break}return s}function qo(r,t,e){let s=[];if(s.push("<!-- auto-context:tentative -->"),s.push("## Existing context (auto-inferred)"),s.push(""),s.push(`_Inferred from title "${r}". Validate before audit \u2014 entries tagged tentative._`),s.push(""),t.length>0){s.push("### Likely paths");for(let n of t)s.push(`- \`${n}\``);s.push("")}if(e.length>0){s.push("### Relevant prior memory");for(let n of e){let i=n.content.length>140?`${n.content.slice(0,137)}\u2026`:n.content,o=Object.entries(n.tags).map(([a,u])=>`${a}:${u}`).join(" ");s.push(`- **${n.type}**${o?` _(${o})_`:""} \u2014 ${i}`)}s.push("")}return s.push("<!-- /auto-context -->"),s.join(`
554
554
  `)}function Go(r,t){let e={level:"warn",code:"no_context_match",message:`No codebase or memory context matched "${r}"`,suggestion:t??"Fill spec.notes manually or run with `--skip-context` next time."};process.stderr.write(`${JSON.stringify(e)}
555
555
  `)}var jn,$o,Wo,Fn=k(()=>{"use strict";lt();Be();jn=5,$o=8,Wo=.15;c(Bo,"inferSpecContext");c(Ho,"dedupeTopDirs");c(qo,"buildNotesBlock");c(Go,"warnNoContextMatch")});var Un={};K(Un,{breakdownSpecToTasks:()=>Yo});async function Yo(r,t,e){let s=e.content.acceptance_criteria;if(s.length===0)return{taskIds:[],skippedReason:"no_acceptance_criteria"};if(e.content.tasks_created_at!==null)return{taskIds:[],skippedReason:"already_broken_down"};let n=!1;if(e.content.linked_tasks.length>0){n=!0,await _t.deleteByFeatureId(r,e.id);let a={...e.content,linked_tasks:[]};v.updateContent(r,e.id,a)}let i=await _t.addTasks(r,s.map(a=>({description:Jo(a),body:a,priority:"medium",type:"feature",section:"backlog",featureId:e.id,groupId:e.id,groupName:e.title})));for(let a of i)v.linkTask(r,e.id,a.id);let o=v.get(r,e.id);if(o){let a={...o.content,tasks_created_at:g()};v.updateContent(r,e.id,a)}return await O.remember(t,{type:"spec",content:`Auto-breakdown: ${i.length} tasks created from ${e.title}${n?" (recovered from partial)":""}`,tags:{spec_id:e.id,event:"auto_breakdown",task_count:String(i.length),...n?{recovered:"partial"}:{}},source:e.id}),{taskIds:i.map(a=>a.id),...n?{recoveredFromPartial:!0}:{}}}function Jo(r){let t=r.replace(/\s+/g," ").trim();return t.length<=140?t:`${t.slice(0,137)}\u2026`}var Xn=k(()=>{"use strict";lt();Ke();Jt();A();c(Yo,"breakdownSpecToTasks");c(Jo,"truncateForDescription")});import{StdioServerTransport as ra}from"@modelcontextprotocol/sdk/server/stdio.js";import{McpServer as ea}from"@modelcontextprotocol/sdk/server/mcp.js";import{z as D}from"zod";Zt();M();X();import tr from"node:fs/promises";import nt from"node:path";function ki(r){let t=[],e,s=new RegExp(us.source,"g");for(;(e=s.exec(r))!==null;){let n=e[1];(n.startsWith(".")||n.startsWith("@/"))&&t.push(n)}return t}c(ki,"extractImportSources");async function Ei(r,t,e){let s;if(r.startsWith("@/"))s=nt.join(e,"src",r.slice(2));else{let n=nt.dirname(nt.join(e,t));s=nt.resolve(n,r)}for(let n of cs){let i=s+n;try{if((await tr.stat(i)).isFile())return nt.relative(e,i)}catch{}}return null}c(Ei,"resolveImport");async function Si(r){let t=await Ts(r),e={},s={},n=0,i=await ks(t,50,async o=>{try{let a=await tr.readFile(nt.join(r,o),"utf-8"),u=ki(a),p=[];for(let m of u){let d=await Ei(m,o,r);d&&d!==o&&p.push(d)}return p.length>0?{filePath:o,imports:p}:null}catch{return null}});for(let{filePath:o,imports:a}of i){e[o]=a,n+=a.length;for(let u of a)s[u]||(s[u]=[]),s[u].push(o)}return{forward:e,reverse:s,fileCount:t.length,edgeCount:n,builtAt:new Date().toISOString()}}c(Si,"buildGraph");function er(r,t,e=2){let s=new Set(r),n=new Map,i=[];for(let o of r){let a=t.forward[o]||[],u=t.reverse[o]||[];for(let p of[...a,...u])s.has(p)||i.push({file:p,depth:1})}for(;i.length>0;){let{file:o,depth:a}=i.shift();if(a>e)continue;let u=1/(a+1),p=n.get(o);if(p){u>p.score&&n.set(o,{score:u,depth:a});continue}if(n.set(o,{score:u,depth:a}),a<e){let m=t.forward[o]||[],d=t.reverse[o]||[];for(let f of[...m,...d])!s.has(f)&&!n.has(f)&&i.push({file:f,depth:a+1})}}return Array.from(n.entries()).map(([o,{score:a,depth:u}])=>({path:o,score:a,depth:u})).sort((o,a)=>a.score-o.score)}c(er,"scoreFromSeeds");var ke="import-graph",Dt=new Map;function wi(r,t){T.setDoc(r,ke,t),Dt.delete(r)}c(wi,"saveGraph");function ht(r){let t=T.get(r,"SELECT updated_at FROM kv_store WHERE key = ?",ke);if(!t)return Dt.delete(r),null;let e=Dt.get(r);if(e&&e.updatedAt===t.updated_at)return e.graph;let s=T.getDoc(r,ke);return s&&Dt.set(r,{graph:s,updatedAt:t.updated_at}),s}c(ht,"loadGraph");async function sr(r,t){let e=await Si(r);return wi(t,e),e}c(sr,"indexImports");function rr(r,t){let e=[...r.added,...r.modified],s=new Set(e),n=new Set,i=ht(t);if(i)for(let u of e){let p=i.reverse[u];if(p)for(let m of p)s.has(m)||n.add(m)}let o=Array.from(n),a=[...e,...o];return{directlyChanged:e,affectedByImports:o,deleted:r.deleted,allAffected:a}}c(rr,"propagateChanges");function nr(r){let t=new Set;for(let e of r){let s=e.toLowerCase();(s.endsWith(".tsx")||s.endsWith(".jsx")||s.endsWith(".css")||s.endsWith(".scss")||s.endsWith(".vue")||s.endsWith(".svelte")||s.includes("/components/")||s.includes("/pages/")||s.includes("/app/"))&&(t.add("frontend"),t.add("uxui")),(s.includes(".test.")||s.includes(".spec.")||s.includes("__tests__")||s.includes("/test/"))&&t.add("testing"),(s.includes("dockerfile")||s.includes("docker-compose")||s.includes(".dockerignore")||s.includes(".github/")||s.includes("ci/")||s.includes("cd/"))&&t.add("devops"),(s.endsWith(".sql")||s.includes("prisma")||s.includes("drizzle")||s.includes("migration")||s.includes("/db/"))&&t.add("database"),(s.endsWith(".ts")||s.endsWith(".js"))&&!s.includes(".test.")&&!s.includes(".spec.")&&!s.endsWith(".d.ts")&&t.add("backend")}return t}c(nr,"affectedDomains");M();rt();async function _i(r,t=100){try{let{stdout:e}=await _(`git log --name-only --pretty=format:'---COMMIT---' -${t}`,{cwd:r,maxBuffer:10485760}),s=[],n=null;for(let i of e.split(`
556
556
  `)){let o=i.trim();o==="---COMMIT---"?(n&&n.size>0&&n.size<=30&&s.push(n),n=new Set):o&&n&&vi(o)&&n.add(o)}return n&&n.size>0&&n.size<=30&&s.push(n),s}catch{return[]}}c(_i,"parseGitLog");function vi(r){return/\.(ts|tsx|js|jsx|mjs|cjs|py|go|rs|java|cs|rb|php|vue|svelte)$/i.test(r)&&!r.includes("node_modules/")}c(vi,"isSourceFile");async function xi(r,t=100){let e=await _i(r,t),s=new Map,n=new Map;for(let o of e){let a=Array.from(o);for(let u of a)s.set(u,(s.get(u)||0)+1);for(let u=0;u<a.length;u++)for(let p=u+1;p<a.length;p++){let m=Pi(a[u],a[p]);n.set(m,(n.get(m)||0)+1)}}let i={};for(let[o,a]of n){let[u,p]=o.split("\0"),m=s.get(u)||0,d=s.get(p)||0;if(m<2||d<2)continue;let f=m+d-a,y=f>0?a/f:0;y<.1||(i[u]||(i[u]={}),i[p]||(i[p]={}),i[u][p]=y,i[p][u]=y)}return{matrix:i,commitsAnalyzed:e.length,filesAnalyzed:s.size,builtAt:new Date().toISOString()}}c(xi,"buildMatrix");function Pi(r,t){return r<t?`${r}\0${t}`:`${t}\0${r}`}c(Pi,"pairKey");function Se(r,t){let e=new Set(r),s=new Map;for(let n of r){let i=t.matrix[n];if(i)for(let[o,a]of Object.entries(i)){if(e.has(o))continue;let u=s.get(o)||0;a>u&&s.set(o,a)}}return Array.from(s.entries()).map(([n,i])=>({path:n,score:i})).sort((n,i)=>i.score-n.score)}c(Se,"scoreFromSeeds");var Ee="cochange-index",Lt=new Map;function Ri(r,t){T.setDoc(r,Ee,t),Lt.delete(r)}c(Ri,"saveMatrix");function we(r){let t=T.get(r,"SELECT updated_at FROM kv_store WHERE key = ?",Ee);if(!t)return Lt.delete(r),null;let e=Lt.get(r);if(e&&e.updatedAt===t.updated_at)return e.matrix;let s=T.getDoc(r,Ee);return s&&Lt.set(r,{matrix:s,updatedAt:t.updated_at}),s}c(we,"loadMatrix");async function ar(r,t,e=100){let s=await xi(r,e);return Ri(t,s),s}c(ar,"indexCoChanges");Tt();async function P(r){return H.getProjectId(r)}c(P,"resolveProjectId");function S(r,t){return async e=>{try{return await t(e)}catch(s){return Mi(s,r)}}}c(S,"safeMcpCall");function Mi(r,t){let e=r instanceof Error?r.message:String(r);return{content:[{type:"text",text:`[${t}] Error: ${e}`}],isError:!0}}c(Mi,"mcpError");function fr(r){let t=r;t.tool("prjct_impact_analysis","Given changed files, find affected files via import graph + affected domains",{projectPath:D.string().describe("Project directory path"),changedFiles:D.array(D.string()).describe("List of changed file paths (relative to project root)")},S("prjct_impact_analysis",async e=>{let s=await P(e.projectPath),n={added:[],modified:e.changedFiles,deleted:[],unchanged:[]},i=rr(n,s),o=nr(i.allAffected),a=["## Impact Analysis"];a.push(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prjct-cli",
3
- "version": "2.19.8",
3
+ "version": "2.20.0",
4
4
  "description": "Context layer for AI agents. Project context for Claude Code, Gemini CLI, and more.",
5
5
  "main": "dist/bin/prjct.mjs",
6
6
  "bin": {