prjct-cli 2.2.2 → 2.2.3
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/CHANGELOG.md +7 -0
- package/dist/bin/prjct-core.mjs +355 -322
- package/dist/bin/prjct.mjs +1 -1
- package/dist/daemon/entry.mjs +310 -278
- package/dist/mcp/server.mjs +2 -2
- package/package.json +1 -1
package/dist/mcp/server.mjs
CHANGED
|
@@ -499,7 +499,7 @@ Total affected: ${o.allAffected.length} files`),{content:[{type:"text",text:a.jo
|
|
|
499
499
|
`)}]}}return{content:[{type:"text",text:["## Import Graph Stats",`Files: ${s.fileCount}`,`Edges: ${s.edgeCount}`,`Built: ${s.builtAt}`].join(`
|
|
500
500
|
`)}]}})),t.tool("prjct_cochange","Files that historically change together (Jaccard similarity from git history)",{projectPath:A.string().describe("Project directory path"),seedFiles:A.array(A.string()).describe("Seed files to find co-change partners for"),rebuild:A.boolean().optional().default(!1).describe("Force rebuild the co-change matrix"),maxResults:A.number().optional().default(10).describe("Max results (default 10)")},S("prjct_cochange",async e=>{let r=await P(e.projectPath),s=e.rebuild?null:Xt(r);s||(s=await sr(e.projectPath,r));let o=Ut(e.seedFiles,s).slice(0,e.maxResults);if(o.length===0)return{content:[{type:"text",text:"No co-change partners found."}]};let i=["## Co-Change Partners",`Seeds: ${e.seedFiles.join(", ")}`,`Commits analyzed: ${s.commitsAnalyzed}`,""];for(let a of o)i.push(`- ${a.path} (similarity: ${Math.round(a.score*100)}%)`);return{content:[{type:"text",text:i.join(`
|
|
501
501
|
`)}]}})),t.tool("prjct_related_context","Combined: import neighbors + co-change partners for seed files",{projectPath:A.string().describe("Project directory path"),seedFiles:A.array(A.string()).describe("Seed files to find related context for"),maxResults:A.number().optional().default(15).describe("Max results (default 15)")},S("prjct_related_context",async e=>{let r=await P(e.projectPath),s=rt(r),o=s?Je(e.seedFiles,s):[],i=Xt(r),a=i?Ut(e.seedFiles,i):[],u=new Map;for(let d of o)u.set(d.path,{importScore:d.score,cochangeScore:0});for(let d of a){let g=u.get(d.path);g?g.cochangeScore=d.score:u.set(d.path,{importScore:0,cochangeScore:d.score})}let p=Array.from(u.entries()).map(([d,g])=>({path:d,combined:g.importScore*.6+g.cochangeScore*.4,importScore:g.importScore,cochangeScore:g.cochangeScore})).sort((d,g)=>g.combined-d.combined).slice(0,e.maxResults);if(p.length===0)return{content:[{type:"text",text:"No related files found. Run `prjct sync` to build indexes."}]};let m=["## Related Context",`Seeds: ${e.seedFiles.join(", ")}`,""];for(let d of p){let g=[];d.importScore>0&&g.push(`import: ${d.importScore.toFixed(2)}`),d.cochangeScore>0&&g.push(`cochange: ${Math.round(d.cochangeScore*100)}%`),m.push(`- ${d.path} (${g.join(", ")})`)}return{content:[{type:"text",text:m.join(`
|
|
502
|
-
`)}]}}))}c(pr,"registerCodeIntelTools");import{z as H}from"zod";import qs from"node:crypto";import{homedir as zs}from"node:os";import{join as Ys}from"node:path";function $(){return qs.randomUUID()}c($,"generateUUID");var na=Ys(zs(),".prjct-cli","projects");At();import{z as l}from"zod";var Js=l.enum(["low","medium","high","critical"]),Et=l.enum(["feature","bug","improvement","chore"]),Vs=l.enum(["active","backlog","previously_active"]),Ks=l.enum(["pending","in_progress","completed","blocked","paused","failed","skipped"]),Qs=l.enum(["task_completed","feature_shipped","idea_captured","session_started"]),Jt=l.object({title:l.string(),description:l.string(),filesChanged:l.array(l.object({path:l.string(),action:l.enum(["created","modified","deleted"])})),whatWasDone:l.array(l.string()).min(1),outputForNextAgent:l.string().min(1),notes:l.string().optional()}),mr=l.object({output:l.string().min(1,"Subtask output is required"),summary:Jt}),gr=l.object({id:l.string(),description:l.string(),domain:l.string(),agent:l.string(),status:Ks,dependsOn:l.array(l.string()),startedAt:l.string().optional(),completedAt:l.string().optional(),output:l.string().optional(),summary:Jt.optional(),skipReason:l.string().optional(),blockReason:l.string().optional(),estimatedPoints:l.number().optional(),estimatedMinutes:l.number().optional()}),fr=l.object({completed:l.number(),total:l.number(),percentage:l.number()}),Vt=l.object({id:l.string(),description:l.string(),type:Et.optional(),startedAt:l.string(),sessionId:l.string(),featureId:l.string().optional(),subtasks:l.array(gr).optional(),currentSubtaskIndex:l.number().optional(),subtaskProgress:fr.optional(),linearId:l.string().optional(),linearUuid:l.string().optional(),estimatedPoints:l.number().optional(),estimatedMinutes:l.number().optional(),modelMetadata:lt.optional(),tokensIn:l.number().optional(),tokensOut:l.number().optional(),parentDescription:l.string().optional(),branch:l.string().optional(),prUrl:l.string().optional()}),dr=l.object({id:l.string(),description:l.string(),status:l.literal("paused"),startedAt:l.string(),pausedAt:l.string(),pauseReason:l.string().optional(),type:Et.optional(),sessionId:l.string().optional(),featureId:l.string().optional(),subtasks:l.array(gr).optional(),currentSubtaskIndex:l.number().optional(),subtaskProgress:fr.optional(),linearId:l.string().optional(),linearUuid:l.string().optional(),estimatedPoints:l.number().optional(),estimatedMinutes:l.number().optional(),modelMetadata:lt.optional(),tokensIn:l.number().optional(),tokensOut:l.number().optional()}),Zs=l.object({stackConfirmed:l.array(l.string()).optional(),patternsDiscovered:l.array(l.string()).optional(),agentAccuracy:l.array(l.object({agent:l.string(),rating:l.enum(["helpful","neutral","inaccurate"]),note:l.string().optional()})).optional(),issuesEncountered:l.array(l.string()).optional()}),tn=l.object({taskId:l.string(),title:l.string(),classification:Et,startedAt:l.string(),completedAt:l.string(),subtaskCount:l.number(),subtaskSummaries:l.array(Jt),outcome:l.string(),branchName:l.string(),linearId:l.string().optional(),linearUuid:l.string().optional(),prUrl:l.string().optional(),feedback:Zs.optional(),tokensIn:l.number().optional(),tokensOut:l.number().optional()}),en=Vt.extend({workspaceId:l.string(),worktreePath:l.string().optional(),agentSessionId:l.string().optional(),jiraId:l.string().optional(),jiraUuid:l.string().optional(),dispatchedFrom:l.string().optional()}),hr=l.object({currentTask:Vt.nullable(),previousTask:dr.nullable().optional(),pausedTasks:l.array(dr).optional(),taskHistory:l.array(tn).optional(),activeTasks:l.array(en).optional(),lastUpdated:l.string()}),yr=l.object({id:l.string(),description:l.string(),body:l.string().optional(),priority:Js,type:Et,featureId:l.string().optional(),originFeature:l.string().optional(),completed:l.boolean(),completedAt:l.string().optional(),createdAt:l.string(),section:Vs,agent:l.string().optional(),groupName:l.string().optional(),groupId:l.string().optional()}),Tr=l.object({tasks:l.array(yr),lastUpdated:l.string()}),rn=l.object({tasksToday:l.number(),tasksThisWeek:l.number(),streak:l.number(),velocity:l.string(),avgDuration:l.string()}),sn=l.object({type:Qs,description:l.string(),timestamp:l.string(),duration:l.string().optional()}),ua=l.object({projectId:l.string(),currentTask:Vt.nullable(),queue:l.array(yr),stats:rn,recentActivity:l.array(sn),lastSync:l.string()});var nt={idle:{transitions:["task"],prompt:"prjct task <description> Start working",description:"No active task"},working:{transitions:["done","pause"],prompt:"prjct status done Complete task | prjct status paused Switch context",description:"Task in progress"},paused:{transitions:["resume","task","ship"],prompt:"prjct status active Continue | prjct task <new> Start different | prjct ship Ship directly",description:"Task paused"},completed:{transitions:["ship","task","pause","reopen"],prompt:"prjct ship Ship it | prjct task <next> Start next | prjct status active Reopen",description:"Task completed"},shipped:{transitions:["task"],prompt:"prjct task <description> Start new task",description:"Feature shipped"}},Kt=class{static{c(this,"WorkflowStateMachine")}getCurrentState(t,e){let r=null;if(e&&t?.activeTasks?.length&&(r=t.activeTasks.find(o=>o.workspaceId===e)),r||(r=t?.currentTask),!r)return(t?.pausedTasks?.length||0)>0||t?.previousTask?.status==="paused"?"paused":"idle";switch((typeof r.status=="string"?r.status:"").toLowerCase()){case"in_progress":case"working":return"working";case"paused":return"paused";case"completed":case"done":return"completed";case"shipped":return"shipped";default:return r?"working":"idle"}}canTransition(t,e){if(nt[t].transitions.includes(e))return{valid:!0};let s=this.formatNextSteps(t).join(" | ");return{valid:!1,error:`Cannot transition to '${e}' from '${t}' state`,suggestion:`Valid next steps: ${s}`}}getNextState(t,e){switch(e){case"task":return"working";case"done":return"completed";case"pause":return"paused";case"resume":return"working";case"ship":return"shipped";case"reopen":return"working";default:return t}}getStateInfo(t){return nt[t]}getPrompt(t){return nt[t].prompt}getValidCommands(t){return nt[t].transitions}formatNextSteps(t){return nt[t].transitions.map(r=>{switch(r){case"task":return"prjct task <desc> Start new task";case"done":return"prjct status done Complete current task";case"pause":return"prjct status paused Pause and switch context";case"resume":return"prjct status active Continue paused task";case"ship":return"prjct ship Ship the feature";case"reopen":return"prjct status active Reopen completed task";default:return`prjct ${r}`}})}},Qt=new Kt;var ot={SHIPPED_RETENTION_DAYS:90,IDEA_DORMANT_DAYS:180,QUEUE_COMPLETED_DAYS:7,PAUSED_TASK_DAYS:30,MEMORY_MAX_ENTRIES:500},Zt=class{static{c(this,"ArchiveStorage")}archive(t,e){let r=$(),s=f();return T.run(t,"INSERT INTO archives (id, entity_type, entity_id, entity_data, summary, archived_at, reason) VALUES (?, ?, ?, ?, ?, ?, ?)",r,e.entityType,e.entityId,JSON.stringify(e.entityData),e.summary??null,s,e.reason),r}archiveMany(t,e){if(e.length===0)return 0;let r=f();return T.transaction(t,s=>{let o=s.prepare("INSERT INTO archives (id, entity_type, entity_id, entity_data, summary, archived_at, reason) VALUES (?, ?, ?, ?, ?, ?, ?)");for(let i of e)o.run($(),i.entityType,i.entityId,JSON.stringify(i.entityData),i.summary??null,r,i.reason)}),e.length}getArchived(t,e,r=50){return e?T.query(t,"SELECT * FROM archives WHERE entity_type = ? ORDER BY archived_at DESC LIMIT ?",e,r):T.query(t,"SELECT * FROM archives ORDER BY archived_at DESC LIMIT ?",r)}getStats(t){let e=T.query(t,"SELECT entity_type, COUNT(*) as count FROM archives GROUP BY entity_type"),r={shipped:0,idea:0,queue_task:0,paused_task:0,memory_entry:0,total:0};for(let s of e){let o=s.entity_type;o in r&&(r[o]=s.count),r.total+=s.count}return r}restore(t,e){let r=T.get(t,"SELECT * FROM archives WHERE id = ?",e);return r?(T.run(t,"DELETE FROM archives WHERE id = ?",e),JSON.parse(r.entity_data)):null}pruneOldArchives(t,e){let r=new Date(Date.now()-e*24*60*60*1e3).toISOString(),s=this.getTotalCount(t);T.run(t,"DELETE FROM archives WHERE archived_at < ?",r);let o=this.getTotalCount(t);return s-o}getTotalCount(t){return T.get(t,"SELECT COUNT(*) as count FROM archives")?.count??0}},K=new Zt;U();var te=class{static{c(this,"SyncEventBus")}async publish(t){let e=b.getSyncPendingPath(t.projectId),r=await ut(e,[])??[],s=Array.isArray(r)?r:[];s.push(t),await M(e,s)}async getPending(t){let e=b.getSyncPendingPath(t),r=await ut(e,[])??[];return Array.isArray(r)?r:[]}async clearPending(t){let e=b.getSyncPendingPath(t);await M(e,[])}async updateLastSync(t){let e=b.getLastSyncPath(t),r={timestamp:f(),success:!0};await M(e,r)}async getLastSync(t){let e=b.getLastSyncPath(t);return await ut(e,null)}},Er=new te;Nt();var Q=class{static{c(this,"StorageManager")}filename;cache;constructor(t,e){this.filename=t,this.cache=new pt({ttl:5e3,maxSize:50})}getStoreKey(){return this.filename.replace(".json","")}async read(t){let e=this.cache.get(t);if(e!==null)return e;try{let r=T.getDoc(t,this.getStoreKey());if(r!==null)return this.cache.set(t,r),r}catch{}return this.getDefault()}async write(t,e){T.setDoc(t,this.getStoreKey(),e),this.cache.set(t,e)}async update(t,e){let r=await this.read(t),s=e(r);return await this.write(t,s),s}async publishEvent(t,e,r){let s={type:e,path:[this.filename.replace(".json","")],data:r,timestamp:f(),projectId:t};await Er.publish(s)}async publishEntityEvent(t,e,r,s){let o=`${e}.${r}`,i={...s,timestamp:f()};await this.publishEvent(t,o,i)}async exists(t){try{return T.hasDoc(t,this.getStoreKey())}catch{return!1}}clearCache(t){t?this.cache.delete(t):this.cache.clear()}getCacheStats(){return this.cache.stats()}};var ee=class extends Q{static{c(this,"StateStorage")}constructor(){super("state.json",hr)}getDefault(){return{currentTask:null,previousTask:null,pausedTasks:[],taskHistory:[],activeTasks:[],lastUpdated:""}}getEventType(t){return`state.${t}d`}validateTransition(t,e){let r=Qt.getCurrentState(t),s=Qt.canTransition(r,e);if(!s.valid)throw new Error(`${s.error}. ${s.suggestion||""}`.trim())}async getCurrentTask(t){return(await this.read(t)).currentTask}async startTask(t,e){let r=await this.read(t);this.validateTransition(r,"task");let s={...e,startedAt:f()};return await this.update(t,o=>({...o,currentTask:s,lastUpdated:f()})),await this.publishEvent(t,"task.started",{taskId:s.id,description:s.description,startedAt:s.startedAt,sessionId:s.sessionId}),s}async updateCurrentTask(t,e){let r=await this.read(t);if(!r.currentTask)return null;let s={...r.currentTask,...e};return await this.update(t,o=>({...o,currentTask:s,lastUpdated:f()})),s}async completeTask(t,e){let r=await this.read(t),s=r.currentTask;if(!s)return null;this.validateTransition(r,"done");let o=f(),i=this.createTaskHistoryEntry(s,o,e),a=this.getTaskHistoryFromState(r),u=[i,...a].slice(0,this.maxTaskHistory);return await this.update(t,p=>({...p,currentTask:null,previousTask:null,taskHistory:u,lastUpdated:o})),await this.publishEvent(t,"task.completed",{taskId:s.id,description:s.description,startedAt:s.startedAt,completedAt:o}),s}createTaskHistoryEntry(t,e,r){let s=(t.subtasks||[]).filter(a=>a.status==="completed"&&a.summary).map(a=>a.summary),o=s.length>0?s.map(a=>a.title).join(", "):"Task completed",i={taskId:t.id,title:t.parentDescription||t.description,classification:t.type||"improvement",startedAt:t.startedAt,completedAt:e,subtaskCount:t.subtasks?.length||0,subtaskSummaries:s,outcome:o,branchName:t.branch||"unknown",linearId:t.linearId,linearUuid:t.linearUuid,prUrl:t.prUrl};return r&&(i.feedback=r),t.tokensIn&&(i.tokensIn=t.tokensIn),t.tokensOut&&(i.tokensOut=t.tokensOut),i}maxPausedTasks=5;maxTaskHistory=20;stalenessThresholdDays=30;async pauseTask(t,e){let r=await this.read(t);if(!r.currentTask)return null;this.validateTransition(r,"pause");let s={...r.currentTask,status:"paused",pausedAt:f(),pauseReason:e},o=this.getPausedTasksFromState(r),i=[s,...o].slice(0,this.maxPausedTasks);return await this.update(t,a=>({...a,currentTask:null,previousTask:null,pausedTasks:i,lastUpdated:f()})),await this.publishEvent(t,"task.paused",{taskId:s.id,description:s.description,pausedAt:s.pausedAt,reason:e,pausedCount:i.length}),s}async resumeTask(t,e){let r=await this.read(t),s=this.getPausedTasksFromState(r);if(s.length===0)return null;this.validateTransition(r,"resume");let o=0;if(e&&(o=s.findIndex(y=>y.id===e),o===-1))return null;let i=s[o],a=s.filter((y,j)=>j!==o),{status:u,pausedAt:p,pauseReason:m,...d}=i,g={...d,startedAt:f(),sessionId:i.sessionId??$()};return await this.update(t,y=>({...y,currentTask:g,previousTask:null,pausedTasks:a,lastUpdated:f()})),await this.publishEvent(t,"task.resumed",{taskId:g.id,description:g.description,resumedAt:g.startedAt,remainingPaused:a.length}),g}getPausedTasksFromState(t){return Array.isArray(t.pausedTasks)&&t.pausedTasks.length>0?t.pausedTasks:t.previousTask?[t.previousTask]:[]}getTaskHistoryFromState(t){return t.taskHistory||[]}async getStalePausedTasks(t){let e=await this.read(t),r=this.getPausedTasksFromState(e),s=Date.now()-this.stalenessThresholdDays*24*60*60*1e3;return r.filter(o=>new Date(o.pausedAt).getTime()<s)}async archiveStalePausedTasks(t){let e=await this.read(t),r=this.getPausedTasksFromState(e),s=Date.now()-this.stalenessThresholdDays*24*60*60*1e3,o=r.filter(a=>new Date(a.pausedAt).getTime()<s),i=r.filter(a=>new Date(a.pausedAt).getTime()>=s);if(o.length===0)return[];K.archiveMany(t,o.map(a=>({entityType:"paused_task",entityId:a.id,entityData:a,summary:a.description,reason:"staleness"}))),await this.update(t,a=>({...a,pausedTasks:i,previousTask:null,lastUpdated:f()}));for(let a of o)await this.publishEvent(t,"task.archived",{taskId:a.id,description:a.description,pausedAt:a.pausedAt,reason:"staleness"});return o}async clearTask(t){await this.update(t,()=>({currentTask:null,previousTask:null,pausedTasks:[],activeTasks:[],lastUpdated:f()}))}async hasTask(t){let e=await this.read(t),r=this.getPausedTasksFromState(e);return e.currentTask!==null||r.length>0}async getPausedTask(t){let e=await this.read(t);return this.getPausedTasksFromState(e)[0]||null}async getAllPausedTasks(t){let e=await this.read(t);return this.getPausedTasksFromState(e)}async getTaskHistory(t){let e=await this.read(t);return this.getTaskHistoryFromState(e)}async getMostRecentTask(t){let e=await this.read(t);return this.getTaskHistoryFromState(e)[0]||null}async getTaskHistoryByType(t,e){let r=await this.read(t);return this.getTaskHistoryFromState(r).filter(o=>o.classification===e)}async getAggregatedFeedback(t){let r=(await this.getTaskHistory(t)).filter(g=>g.feedback),s=[],o=[],i=[],a=[];for(let g of r){let y=g.feedback;Array.isArray(y.stackConfirmed)&&s.push(...y.stackConfirmed),Array.isArray(y.patternsDiscovered)&&o.push(...y.patternsDiscovered),Array.isArray(y.agentAccuracy)&&i.push(...y.agentAccuracy),Array.isArray(y.issuesEncountered)&&a.push(...y.issuesEncountered)}let u=[...new Set(s)],p=[...new Set(o)],m=new Map;for(let g of a)m.set(g,(m.get(g)||0)+1);let d=[...m.entries()].filter(([g,y])=>y>=2).map(([g])=>g);return{stackConfirmed:u,patternsDiscovered:p,agentAccuracy:i,issuesEncountered:[...new Set(a)],knownGotchas:d}}async startTaskInWorkspace(t,e,r){let s={...e,workspaceId:r,startedAt:f()};return await this.update(t,o=>({...o,activeTasks:[...o.activeTasks||[],s],lastUpdated:f()})),await this.publishEvent(t,"task.started",{taskId:s.id,description:s.description,startedAt:s.startedAt,sessionId:s.sessionId,workspaceId:r}),s}async getCurrentTaskForWorkspace(t,e){return((await this.read(t)).activeTasks||[]).find(s=>s.workspaceId===e)??null}async completeTaskInWorkspace(t,e,r){let s=await this.read(t),i=(s.activeTasks||[]).find(d=>d.workspaceId===e);if(!i)return null;let a=f(),u=this.createTaskHistoryEntry(i,a,r),p=this.getTaskHistoryFromState(s),m=[u,...p].slice(0,this.maxTaskHistory);return await this.update(t,d=>({...d,activeTasks:(d.activeTasks||[]).filter(g=>g.workspaceId!==e),taskHistory:m,lastUpdated:a})),await this.publishEvent(t,"task.completed",{taskId:i.id,description:i.description,startedAt:i.startedAt,completedAt:a,workspaceId:e}),i}async getActiveTasks(t){return(await this.read(t)).activeTasks||[]}async getActiveTaskCount(t){return((await this.read(t)).activeTasks||[]).length}async updateWorkspaceTask(t,e,r){let o=(await this.read(t)).activeTasks||[],i=o.findIndex(u=>u.workspaceId===e);if(i===-1)return null;let a={...o[i],...r,workspaceId:e};return await this.update(t,u=>{let p=[...u.activeTasks||[]];return p[i]=a,{...u,activeTasks:p,lastUpdated:f()}}),a}async addTokens(t,e,r){let s=await this.read(t);if(!s.currentTask)return null;let o=(s.currentTask.tokensIn||0)+e,i=(s.currentTask.tokensOut||0)+r;return await this.update(t,a=>({...a,currentTask:{...a.currentTask,tokensIn:o,tokensOut:i},lastUpdated:f()})),{tokensIn:o,tokensOut:i}}async createSubtasks(t,e){let r=await this.read(t);if(!r.currentTask)return;let s=e.map((o,i)=>({...o,status:i===0?"in_progress":"pending",startedAt:i===0?f():void 0,dependsOn:o.dependsOn||[]}));await this.update(t,o=>({...o,currentTask:{...o.currentTask,subtasks:s,currentSubtaskIndex:0,subtaskProgress:{completed:0,total:s.length,percentage:0}},lastUpdated:f()})),await this.publishEvent(t,"subtasks.created",{taskId:r.currentTask.id,subtaskCount:s.length,subtasks:s.map(o=>({id:o.id,description:o.description,domain:o.domain}))})}async completeSubtask(t,e){let r=mr.safeParse(e);if(!r.success){let j=r.error.issues.map(at=>`${at.path.join(".")}: ${at.message}`);throw new Error(`Subtask completion requires handoff data:
|
|
502
|
+
`)}]}}))}c(pr,"registerCodeIntelTools");import{z as H}from"zod";import qs from"node:crypto";import{homedir as zs}from"node:os";import{join as Ys}from"node:path";function $(){return qs.randomUUID()}c($,"generateUUID");var na=Ys(zs(),".prjct-cli","projects");At();import{z as l}from"zod";var Js=l.enum(["low","medium","high","critical"]),Et=l.enum(["feature","bug","improvement","chore"]),Vs=l.enum(["active","backlog","previously_active"]),Ks=l.enum(["pending","in_progress","completed","blocked","paused","failed","skipped"]),Qs=l.enum(["task_completed","feature_shipped","idea_captured","session_started"]),Jt=l.object({title:l.string(),description:l.string(),filesChanged:l.array(l.object({path:l.string(),action:l.enum(["created","modified","deleted"])})),whatWasDone:l.array(l.string()).min(1),outputForNextAgent:l.string().min(1),notes:l.string().optional()}),mr=l.object({output:l.string().min(1,"Subtask output is required"),summary:Jt}),gr=l.object({id:l.string(),description:l.string(),domain:l.string(),agent:l.string(),status:Ks,dependsOn:l.array(l.string()),startedAt:l.string().optional(),completedAt:l.string().optional(),output:l.string().optional(),summary:Jt.optional(),skipReason:l.string().optional(),blockReason:l.string().optional(),estimatedPoints:l.number().optional(),estimatedMinutes:l.number().optional()}),fr=l.object({completed:l.number(),total:l.number(),percentage:l.number()}),Vt=l.object({id:l.string(),description:l.string(),type:Et.optional(),startedAt:l.string(),sessionId:l.string(),featureId:l.string().optional(),subtasks:l.array(gr).optional(),currentSubtaskIndex:l.number().optional(),subtaskProgress:fr.optional(),linearId:l.string().optional(),linearUuid:l.string().optional(),estimatedPoints:l.number().optional(),estimatedMinutes:l.number().optional(),modelMetadata:lt.optional(),tokensIn:l.number().optional(),tokensOut:l.number().optional(),parentDescription:l.string().optional(),branch:l.string().optional(),prUrl:l.string().optional()}),dr=l.object({id:l.string(),description:l.string(),status:l.literal("paused"),startedAt:l.string(),pausedAt:l.string(),pauseReason:l.string().optional(),type:Et.optional(),sessionId:l.string().optional(),featureId:l.string().optional(),subtasks:l.array(gr).optional(),currentSubtaskIndex:l.number().optional(),subtaskProgress:fr.optional(),linearId:l.string().optional(),linearUuid:l.string().optional(),estimatedPoints:l.number().optional(),estimatedMinutes:l.number().optional(),modelMetadata:lt.optional(),tokensIn:l.number().optional(),tokensOut:l.number().optional()}),Zs=l.object({stackConfirmed:l.array(l.string()).optional(),patternsDiscovered:l.array(l.string()).optional(),agentAccuracy:l.array(l.object({agent:l.string(),rating:l.enum(["helpful","neutral","inaccurate"]),note:l.string().optional()})).optional(),issuesEncountered:l.array(l.string()).optional()}),tn=l.object({taskId:l.string(),title:l.string(),classification:Et,startedAt:l.string(),completedAt:l.string(),subtaskCount:l.number(),subtaskSummaries:l.array(Jt),outcome:l.string(),branchName:l.string(),linearId:l.string().optional(),linearUuid:l.string().optional(),prUrl:l.string().optional(),feedback:Zs.optional(),tokensIn:l.number().optional(),tokensOut:l.number().optional()}),en=Vt.extend({workspaceId:l.string(),worktreePath:l.string().optional(),agentSessionId:l.string().optional(),jiraId:l.string().optional(),jiraUuid:l.string().optional(),dispatchedFrom:l.string().optional()}),hr=l.object({currentTask:Vt.nullable(),previousTask:dr.nullable().optional(),pausedTasks:l.array(dr).optional(),taskHistory:l.array(tn).optional(),activeTasks:l.array(en).optional(),lastUpdated:l.string()}),yr=l.object({id:l.string(),description:l.string(),body:l.string().optional(),priority:Js,type:Et,featureId:l.string().optional(),originFeature:l.string().optional(),completed:l.boolean(),completedAt:l.string().optional(),createdAt:l.string(),section:Vs,agent:l.string().optional(),groupName:l.string().optional(),groupId:l.string().optional()}),Tr=l.object({tasks:l.array(yr),lastUpdated:l.string()}),rn=l.object({tasksToday:l.number(),tasksThisWeek:l.number(),streak:l.number(),velocity:l.string(),avgDuration:l.string()}),sn=l.object({type:Qs,description:l.string(),timestamp:l.string(),duration:l.string().optional()}),ua=l.object({projectId:l.string(),currentTask:Vt.nullable(),queue:l.array(yr),stats:rn,recentActivity:l.array(sn),lastSync:l.string()});var nt={idle:{transitions:["task"],prompt:"prjct task <description> Start working",description:"No active task"},working:{transitions:["done","pause"],prompt:"prjct status done Complete task | prjct status paused Switch context",description:"Task in progress"},paused:{transitions:["resume","task","ship"],prompt:"prjct status active Continue | prjct task <new> Start different | prjct ship Ship directly",description:"Task paused"},completed:{transitions:["ship","task","pause","reopen"],prompt:"prjct ship Ship it | prjct task <next> Start next | prjct status active Reopen",description:"Task completed"},shipped:{transitions:["task"],prompt:"prjct task <description> Start new task",description:"Feature shipped"}},Kt=class{static{c(this,"WorkflowStateMachine")}getCurrentState(t,e){let r=null;if(e&&t?.activeTasks?.length&&(r=t.activeTasks.find(o=>o.workspaceId===e)),r||(r=t?.currentTask),!r)return(t?.pausedTasks?.length||0)>0||t?.previousTask?.status==="paused"?"paused":"idle";switch((typeof r.status=="string"?r.status:"").toLowerCase()){case"in_progress":case"working":return"working";case"paused":return"paused";case"completed":case"done":return"completed";case"shipped":return"shipped";default:return r?"working":"idle"}}canTransition(t,e){if(nt[t].transitions.includes(e))return{valid:!0};let s=this.formatNextSteps(t).join(" | ");return{valid:!1,error:`Cannot transition to '${e}' from '${t}' state`,suggestion:`Valid next steps: ${s}`}}getNextState(t,e){switch(e){case"task":return"working";case"done":return"completed";case"pause":return"paused";case"resume":return"working";case"ship":return"shipped";case"reopen":return"working";default:return t}}getStateInfo(t){return nt[t]}getPrompt(t){return nt[t].prompt}getValidCommands(t){return nt[t].transitions}formatNextSteps(t){return nt[t].transitions.map(r=>{switch(r){case"task":return"prjct task <desc> Start new task";case"done":return"prjct status done Complete current task";case"pause":return"prjct status paused Pause and switch context";case"resume":return"prjct status active Continue paused task";case"ship":return"prjct ship Ship the feature";case"reopen":return"prjct status active Reopen completed task";default:return`prjct ${r}`}})}},Qt=new Kt;var ot={SHIPPED_RETENTION_DAYS:90,IDEA_DORMANT_DAYS:180,QUEUE_COMPLETED_DAYS:7,PAUSED_TASK_DAYS:30,MEMORY_MAX_ENTRIES:500},Zt=class{static{c(this,"ArchiveStorage")}archive(t,e){let r=$(),s=f();return T.run(t,"INSERT INTO archives (id, entity_type, entity_id, entity_data, summary, archived_at, reason) VALUES (?, ?, ?, ?, ?, ?, ?)",r,e.entityType,e.entityId,JSON.stringify(e.entityData),e.summary??null,s,e.reason),r}archiveMany(t,e){if(e.length===0)return 0;let r=f();return T.transaction(t,s=>{let o=s.prepare("INSERT INTO archives (id, entity_type, entity_id, entity_data, summary, archived_at, reason) VALUES (?, ?, ?, ?, ?, ?, ?)");for(let i of e)o.run($(),i.entityType,i.entityId,JSON.stringify(i.entityData),i.summary??null,r,i.reason)}),e.length}getArchived(t,e,r=50){return e?T.query(t,"SELECT * FROM archives WHERE entity_type = ? ORDER BY archived_at DESC LIMIT ?",e,r):T.query(t,"SELECT * FROM archives ORDER BY archived_at DESC LIMIT ?",r)}getStats(t){let e=T.query(t,"SELECT entity_type, COUNT(*) as count FROM archives GROUP BY entity_type"),r={shipped:0,idea:0,queue_task:0,paused_task:0,memory_entry:0,total:0};for(let s of e){let o=s.entity_type;o in r&&(r[o]=s.count),r.total+=s.count}return r}restore(t,e){let r=T.get(t,"SELECT * FROM archives WHERE id = ?",e);return r?(T.run(t,"DELETE FROM archives WHERE id = ?",e),JSON.parse(r.entity_data)):null}pruneOldArchives(t,e){let r=new Date(Date.now()-e*24*60*60*1e3).toISOString(),s=this.getTotalCount(t);T.run(t,"DELETE FROM archives WHERE archived_at < ?",r);let o=this.getTotalCount(t);return s-o}getTotalCount(t){return T.get(t,"SELECT COUNT(*) as count FROM archives")?.count??0}},K=new Zt;U();var te=class{static{c(this,"SyncEventBus")}async publish(t){let e=b.getSyncPendingPath(t.projectId),r=await ut(e,[])??[],s=Array.isArray(r)?r:[];s.push(t),await M(e,s)}async getPending(t){let e=b.getSyncPendingPath(t),r=await ut(e,[])??[];return Array.isArray(r)?r:[]}async clearPending(t){let e=b.getSyncPendingPath(t);await M(e,[])}async updateLastSync(t){let e=b.getLastSyncPath(t),r={timestamp:f(),success:!0};await M(e,r)}async getLastSync(t){let e=b.getLastSyncPath(t);return await ut(e,null)}},Er=new te;Nt();var Q=class{static{c(this,"StorageManager")}filename;cache;constructor(t,e){this.filename=t,this.cache=new pt({ttl:5e3,maxSize:50})}getStoreKey(){return this.filename.replace(".json","")}async read(t){let e=this.cache.get(t);if(e!==null)return e;try{let r=T.getDoc(t,this.getStoreKey());if(r!==null)return this.cache.set(t,r),r}catch{}return this.getDefault()}async write(t,e){T.setDoc(t,this.getStoreKey(),e),this.cache.set(t,e)}async update(t,e){let r=await this.read(t),s=e(r);return await this.write(t,s),s}async publishEvent(t,e,r){let s={type:e,path:[this.filename.replace(".json","")],data:r,timestamp:f(),projectId:t};await Er.publish(s)}async publishEntityEvent(t,e,r,s){let o=`${e}.${r}`,i={...s,timestamp:f()};await this.publishEvent(t,o,i)}async exists(t){try{return T.hasDoc(t,this.getStoreKey())}catch{return!1}}clearCache(t){t?this.cache.delete(t):this.cache.clear()}getCacheStats(){return this.cache.stats()}};var ee=class extends Q{static{c(this,"StateStorage")}constructor(){super("state.json",hr)}getDefault(){return{currentTask:null,previousTask:null,pausedTasks:[],taskHistory:[],activeTasks:[],lastUpdated:""}}getEventType(t){return`state.${t}d`}validateTransition(t,e){let r=Qt.getCurrentState(t),s=Qt.canTransition(r,e);if(!s.valid)throw new Error(`${s.error}. ${s.suggestion||""}`.trim())}async getCurrentTask(t){return(await this.read(t)).currentTask}async getPausedTasks(t){let e=await this.read(t);return this.getPausedTasksFromState(e)}async startTask(t,e){let r=await this.read(t);this.validateTransition(r,"task");let s={...e,startedAt:f()};return await this.update(t,o=>({...o,currentTask:s,lastUpdated:f()})),await this.publishEvent(t,"task.started",{taskId:s.id,description:s.description,startedAt:s.startedAt,sessionId:s.sessionId}),s}async updateCurrentTask(t,e){let r=await this.read(t);if(!r.currentTask)return null;let s={...r.currentTask,...e};return await this.update(t,o=>({...o,currentTask:s,lastUpdated:f()})),s}async completeTask(t,e){let r=await this.read(t),s=r.currentTask;if(!s)return null;this.validateTransition(r,"done");let o=f(),i=this.createTaskHistoryEntry(s,o,e),a=this.getTaskHistoryFromState(r),u=[i,...a].slice(0,this.maxTaskHistory);return await this.update(t,p=>({...p,currentTask:null,previousTask:null,taskHistory:u,lastUpdated:o})),await this.publishEvent(t,"task.completed",{taskId:s.id,description:s.description,startedAt:s.startedAt,completedAt:o}),s}createTaskHistoryEntry(t,e,r){let s=(t.subtasks||[]).filter(a=>a.status==="completed"&&a.summary).map(a=>a.summary),o=s.length>0?s.map(a=>a.title).join(", "):"Task completed",i={taskId:t.id,title:t.parentDescription||t.description,classification:t.type||"improvement",startedAt:t.startedAt,completedAt:e,subtaskCount:t.subtasks?.length||0,subtaskSummaries:s,outcome:o,branchName:t.branch||"unknown",linearId:t.linearId,linearUuid:t.linearUuid,prUrl:t.prUrl};return r&&(i.feedback=r),t.tokensIn&&(i.tokensIn=t.tokensIn),t.tokensOut&&(i.tokensOut=t.tokensOut),i}maxPausedTasks=5;maxTaskHistory=20;stalenessThresholdDays=30;async pauseTask(t,e){let r=await this.read(t);if(!r.currentTask)return null;this.validateTransition(r,"pause");let s={...r.currentTask,status:"paused",pausedAt:f(),pauseReason:e},o=this.getPausedTasksFromState(r),i=[s,...o].slice(0,this.maxPausedTasks);return await this.update(t,a=>({...a,currentTask:null,previousTask:null,pausedTasks:i,lastUpdated:f()})),await this.publishEvent(t,"task.paused",{taskId:s.id,description:s.description,pausedAt:s.pausedAt,reason:e,pausedCount:i.length}),s}async resumeTask(t,e){let r=await this.read(t),s=this.getPausedTasksFromState(r);if(s.length===0)return null;this.validateTransition(r,"resume");let o=0;if(e&&(o=s.findIndex(y=>y.id===e),o===-1))return null;let i=s[o],a=s.filter((y,j)=>j!==o),{status:u,pausedAt:p,pauseReason:m,...d}=i,g={...d,startedAt:f(),sessionId:i.sessionId??$()};return await this.update(t,y=>({...y,currentTask:g,previousTask:null,pausedTasks:a,lastUpdated:f()})),await this.publishEvent(t,"task.resumed",{taskId:g.id,description:g.description,resumedAt:g.startedAt,remainingPaused:a.length}),g}getPausedTasksFromState(t){return Array.isArray(t.pausedTasks)&&t.pausedTasks.length>0?t.pausedTasks:t.previousTask?[t.previousTask]:[]}getTaskHistoryFromState(t){return t.taskHistory||[]}async getStalePausedTasks(t){let e=await this.read(t),r=this.getPausedTasksFromState(e),s=Date.now()-this.stalenessThresholdDays*24*60*60*1e3;return r.filter(o=>new Date(o.pausedAt).getTime()<s)}async archiveStalePausedTasks(t){let e=await this.read(t),r=this.getPausedTasksFromState(e),s=Date.now()-this.stalenessThresholdDays*24*60*60*1e3,o=r.filter(a=>new Date(a.pausedAt).getTime()<s),i=r.filter(a=>new Date(a.pausedAt).getTime()>=s);if(o.length===0)return[];K.archiveMany(t,o.map(a=>({entityType:"paused_task",entityId:a.id,entityData:a,summary:a.description,reason:"staleness"}))),await this.update(t,a=>({...a,pausedTasks:i,previousTask:null,lastUpdated:f()}));for(let a of o)await this.publishEvent(t,"task.archived",{taskId:a.id,description:a.description,pausedAt:a.pausedAt,reason:"staleness"});return o}async clearTask(t){await this.update(t,()=>({currentTask:null,previousTask:null,pausedTasks:[],activeTasks:[],lastUpdated:f()}))}async hasTask(t){let e=await this.read(t),r=this.getPausedTasksFromState(e);return e.currentTask!==null||r.length>0}async getPausedTask(t){let e=await this.read(t);return this.getPausedTasksFromState(e)[0]||null}async getAllPausedTasks(t){let e=await this.read(t);return this.getPausedTasksFromState(e)}async getTaskHistory(t){let e=await this.read(t);return this.getTaskHistoryFromState(e)}async getMostRecentTask(t){let e=await this.read(t);return this.getTaskHistoryFromState(e)[0]||null}async getTaskHistoryByType(t,e){let r=await this.read(t);return this.getTaskHistoryFromState(r).filter(o=>o.classification===e)}async getAggregatedFeedback(t){let r=(await this.getTaskHistory(t)).filter(g=>g.feedback),s=[],o=[],i=[],a=[];for(let g of r){let y=g.feedback;Array.isArray(y.stackConfirmed)&&s.push(...y.stackConfirmed),Array.isArray(y.patternsDiscovered)&&o.push(...y.patternsDiscovered),Array.isArray(y.agentAccuracy)&&i.push(...y.agentAccuracy),Array.isArray(y.issuesEncountered)&&a.push(...y.issuesEncountered)}let u=[...new Set(s)],p=[...new Set(o)],m=new Map;for(let g of a)m.set(g,(m.get(g)||0)+1);let d=[...m.entries()].filter(([g,y])=>y>=2).map(([g])=>g);return{stackConfirmed:u,patternsDiscovered:p,agentAccuracy:i,issuesEncountered:[...new Set(a)],knownGotchas:d}}async startTaskInWorkspace(t,e,r){let s={...e,workspaceId:r,startedAt:f()};return await this.update(t,o=>({...o,activeTasks:[...o.activeTasks||[],s],lastUpdated:f()})),await this.publishEvent(t,"task.started",{taskId:s.id,description:s.description,startedAt:s.startedAt,sessionId:s.sessionId,workspaceId:r}),s}async getCurrentTaskForWorkspace(t,e){return((await this.read(t)).activeTasks||[]).find(s=>s.workspaceId===e)??null}async completeTaskInWorkspace(t,e,r){let s=await this.read(t),i=(s.activeTasks||[]).find(d=>d.workspaceId===e);if(!i)return null;let a=f(),u=this.createTaskHistoryEntry(i,a,r),p=this.getTaskHistoryFromState(s),m=[u,...p].slice(0,this.maxTaskHistory);return await this.update(t,d=>({...d,activeTasks:(d.activeTasks||[]).filter(g=>g.workspaceId!==e),taskHistory:m,lastUpdated:a})),await this.publishEvent(t,"task.completed",{taskId:i.id,description:i.description,startedAt:i.startedAt,completedAt:a,workspaceId:e}),i}async getActiveTasks(t){return(await this.read(t)).activeTasks||[]}async getActiveTaskCount(t){return((await this.read(t)).activeTasks||[]).length}async updateWorkspaceTask(t,e,r){let o=(await this.read(t)).activeTasks||[],i=o.findIndex(u=>u.workspaceId===e);if(i===-1)return null;let a={...o[i],...r,workspaceId:e};return await this.update(t,u=>{let p=[...u.activeTasks||[]];return p[i]=a,{...u,activeTasks:p,lastUpdated:f()}}),a}async addTokens(t,e,r){let s=await this.read(t);if(!s.currentTask)return null;let o=(s.currentTask.tokensIn||0)+e,i=(s.currentTask.tokensOut||0)+r;return await this.update(t,a=>({...a,currentTask:{...a.currentTask,tokensIn:o,tokensOut:i},lastUpdated:f()})),{tokensIn:o,tokensOut:i}}async createSubtasks(t,e){let r=await this.read(t);if(!r.currentTask)return;let s=e.map((o,i)=>({...o,status:i===0?"in_progress":"pending",startedAt:i===0?f():void 0,dependsOn:o.dependsOn||[]}));await this.update(t,o=>({...o,currentTask:{...o.currentTask,subtasks:s,currentSubtaskIndex:0,subtaskProgress:{completed:0,total:s.length,percentage:0}},lastUpdated:f()})),await this.publishEvent(t,"subtasks.created",{taskId:r.currentTask.id,subtaskCount:s.length,subtasks:s.map(o=>({id:o.id,description:o.description,domain:o.domain}))})}async completeSubtask(t,e){let r=mr.safeParse(e);if(!r.success){let j=r.error.issues.map(at=>`${at.path.join(".")}: ${at.message}`);throw new Error(`Subtask completion requires handoff data:
|
|
503
503
|
${j.join(`
|
|
504
504
|
`)}`)}let{output:s,summary:o}=r.data,i=await this.read(t);if(!i.currentTask?.subtasks)return null;let a=i.currentTask.currentSubtaskIndex||0,u=i.currentTask.subtasks[a];if(!u)return null;let p=[...i.currentTask.subtasks];p[a]={...u,status:"completed",completedAt:f(),output:s,summary:o};let m=p.filter(j=>j.status==="completed").length,d=p.length,g=Math.round(m/d*100),y=a+1;return y<p.length&&(p[y]={...p[y],status:"in_progress",startedAt:f()}),await this.update(t,j=>({...j,currentTask:{...j.currentTask,subtasks:p,currentSubtaskIndex:y<d?y:a,subtaskProgress:{completed:m,total:d,percentage:g}},lastUpdated:f()})),await this.publishEvent(t,"subtask.completed",{taskId:i.currentTask.id,subtaskId:u.id,description:u.description,output:s,handoff:o.outputForNextAgent,filesChanged:o.filesChanged.length,progress:{completed:m,total:d,percentage:g}}),y<d?p[y]:null}async getCurrentSubtask(t){let e=await this.read(t);if(!e.currentTask?.subtasks)return null;let r=e.currentTask.currentSubtaskIndex||0;return e.currentTask.subtasks[r]||null}async getNextSubtask(t){let e=await this.read(t);if(!e.currentTask?.subtasks)return null;let r=(e.currentTask.currentSubtaskIndex||0)+1;return e.currentTask.subtasks[r]||null}async getPreviousSubtask(t){let e=await this.read(t);if(!e.currentTask?.subtasks)return null;let r=(e.currentTask.currentSubtaskIndex||0)-1;return r<0?null:e.currentTask.subtasks[r]||null}async getPreviousHandoff(t){let e=await this.getPreviousSubtask(t);return e?.summary?.outputForNextAgent?{fromSubtask:e.description,outputForNextAgent:e.summary.outputForNextAgent,filesChanged:e.summary.filesChanged,whatWasDone:e.summary.whatWasDone}:null}async getSubtasks(t){return(await this.read(t)).currentTask?.subtasks||[]}async getSubtaskProgress(t){return(await this.read(t)).currentTask?.subtaskProgress||null}async hasSubtasks(t){return((await this.read(t)).currentTask?.subtasks?.length||0)>0}async areAllSubtasksComplete(t){let e=await this.read(t);return e.currentTask?.subtasks?e.currentTask.subtasks.every(r=>r.status==="completed"||r.status==="failed"||r.status==="skipped"):!0}async failSubtask(t,e){let r=await this.read(t);if(!r.currentTask?.subtasks)return null;let s=r.currentTask.currentSubtaskIndex||0,o=r.currentTask.subtasks[s];if(!o)return null;let i=[...r.currentTask.subtasks];i[s]={...o,status:"failed",completedAt:f(),output:`Failed: ${e}`};let a=s+1,u=i.length;a<u&&(i[a]={...i[a],status:"in_progress",startedAt:f()});let p=i.filter(d=>d.status==="completed"||d.status==="failed"||d.status==="skipped").length,m=Math.round(p/u*100);return await this.update(t,d=>({...d,currentTask:{...d.currentTask,subtasks:i,currentSubtaskIndex:a<u?a:s,subtaskProgress:{completed:p,total:u,percentage:m}},lastUpdated:f()})),await this.publishEvent(t,"subtask.failed",{taskId:r.currentTask.id,subtaskId:o.id,description:o.description,error:e}),a<u?i[a]:null}async skipSubtask(t,e){let r=await this.read(t);if(!r.currentTask?.subtasks)return null;let s=r.currentTask.currentSubtaskIndex||0,o=r.currentTask.subtasks[s];if(!o)return null;let i=[...r.currentTask.subtasks];i[s]={...o,status:"skipped",completedAt:f(),output:`Skipped: ${e}`,skipReason:e};let a=s+1,u=i.length;a<u&&(i[a]={...i[a],status:"in_progress",startedAt:f()});let p=i.filter(d=>d.status==="completed"||d.status==="failed"||d.status==="skipped").length,m=Math.round(p/u*100);return await this.update(t,d=>({...d,currentTask:{...d.currentTask,subtasks:i,currentSubtaskIndex:a<u?a:s,subtaskProgress:{completed:p,total:u,percentage:m}},lastUpdated:f()})),await this.publishEvent(t,"subtask.skipped",{taskId:r.currentTask.id,subtaskId:o.id,description:o.description,reason:e}),a<u?i[a]:null}async blockSubtask(t,e){let r=await this.read(t);if(!r.currentTask?.subtasks)return null;let s=r.currentTask.currentSubtaskIndex||0,o=r.currentTask.subtasks[s];if(!o)return null;let i=[...r.currentTask.subtasks];i[s]={...o,status:"blocked",output:`Blocked: ${e}`,blockReason:e};let a=s+1,u=i.length;return a<u&&(i[a]={...i[a],status:"in_progress",startedAt:f()}),await this.update(t,p=>({...p,currentTask:{...p.currentTask,subtasks:i,currentSubtaskIndex:a<u?a:s},lastUpdated:f()})),await this.publishEvent(t,"subtask.blocked",{taskId:r.currentTask.id,subtaskId:o.id,description:o.description,blocker:e}),a<u?i[a]:null}},Z=new ee;W();z();import nn from"node:fs/promises";import kt from"node:path";var on={frontend:["component","page","view","ui","layout","style","css","scss","sass","hook","context","store","redux","zustand","react","vue","svelte","angular","next","nuxt","app","client"],backend:["api","route","controller","service","middleware","handler","resolver","schema","model","entity","repository","server","socket","graphql","rest","trpc"],database:["migration","seed","schema","model","entity","repository","prisma","drizzle","sequelize","typeorm","mongoose","knex","sql","db"],auth:["auth","login","logout","session","token","jwt","oauth","passport","credential","permission","role","user","account"],testing:["test","spec","e2e","integration","unit","mock","fixture","stub","jest","vitest","cypress","playwright"],config:["config","env","setting","constant","option","tsconfig","eslint","prettier","vite","webpack","rollup"],infra:["docker","compose","kubernetes","k8s","ci","cd","github","gitlab","jenkins","terraform","ansible","deploy"],util:["util","helper","lib","common","shared","core","base","abstract"]},an=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs",".py",".go",".rs",".java",".kt",".swift",".rb",".php",".c",".cpp",".h",".hpp",".cs",".vue",".svelte"]),cn=new Set(["node_modules",".git","dist","build",".next",".nuxt",".output","coverage",".cache","__pycache__",".pytest_cache","vendor","target",".turbo",".vercel"]);async function kr(n,t,e={}){let r=Date.now(),s=e.maxFiles??30,o=e.minScore??.1,i=e.includeTests??!1,a=un(n),u=await ln(t),p=await pn(t),m=[];for(let g of u){if(!i&&mn(g))continue;let y=dn(g,a,p,e.historicalBoosts);y.score>=o&&m.push(y)}m.sort((g,y)=>y.score-g.score);let d=m.slice(0,s);return{files:d,metrics:{filesScanned:u.length,filesReturned:d.length,scanDuration:Date.now()-r}}}c(kr,"findRelevantFiles");function un(n){let t=n.toLowerCase().split(/[^a-z0-9]+/).filter(Boolean),e=new Set(["a","an","the","and","or","but","is","are","was","were","be","been","being","have","has","had","do","does","did","will","would","could","should","may","might","must","shall","can","need","to","of","in","for","on","with","at","by","from","as","into","through","during","before","after","above","below","between","under","again","further","then","once","here","there","when","where","why","how","all","each","few","more","most","other","some","such","no","nor","not","only","own","same","so","than","too","very","just","add","create","make","implement","fix","update","change","modify","remove","delete","new"]);return t.filter(r=>!e.has(r)&&r.length>2)}c(un,"extractKeywords");async function ln(n){let t=[];async function e(r,s=""){try{let o=await nn.readdir(r,{withFileTypes:!0});for(let i of o){let a=kt.join(r,i.name),u=kt.join(s,i.name);if(i.isDirectory()){if(cn.has(i.name)||i.name.startsWith("."))continue;await e(a,u)}else if(i.isFile()){let p=kt.extname(i.name).toLowerCase();an.has(p)&&t.push(u)}}}catch(o){N(o)}}return c(e,"walk"),await e(n),t}c(ln,"getAllCodeFiles");async function pn(n){let t=new Map;try{let{stdout:e}=await k(`git log -30 --pretty=format:"%H %ct" --name-only | awk '
|
|
505
505
|
/^[a-f0-9]{40}/ { commit=$1; timestamp=$2; next }
|
|
@@ -520,7 +520,7 @@ ${s.join(`
|
|
|
520
520
|
|
|
521
521
|
${i.join(`
|
|
522
522
|
`)}`}]}}))}c(Pr,"registerFileTools");import{z as v}from"zod";var se=class{static{c(this,"MemoryService")}async log(t,e,r,s){try{let o=await B.getProjectId(t);if(!o)return;E.appendEvent(o,`memory.${e}`,{...r,author:s})}catch(o){console.error(`Memory log error: ${o instanceof Error?o.message:String(o)}`)}}async getRecent(t,e=100){try{let r=await B.getProjectId(t);return r?E.query(r,"SELECT type, data, timestamp FROM events WHERE type LIKE 'memory.%' ORDER BY id DESC LIMIT ?",e).reverse().map(o=>{let i=JSON.parse(o.data),{author:a,...u}=i;return{timestamp:o.timestamp,action:o.type.replace("memory.",""),data:u,author:a}}):[]}catch(r){return console.error(`Memory read error: ${r instanceof Error?r.message:String(r)}`),[]}}async search(t,e,r=50){let s=await this.getRecent(t,1e3),o=e.toLowerCase();return s.filter(i=>{let a=i.action.toLowerCase().includes(o),u=JSON.stringify(i.data).toLowerCase().includes(o);return a||u}).slice(-r)}async getByAction(t,e,r=50){try{let s=await B.getProjectId(t);return s?E.query(s,"SELECT type, data, timestamp FROM events WHERE type = ? ORDER BY id DESC LIMIT ?",`memory.${e}`,r).reverse().map(i=>{let a=JSON.parse(i.data),{author:u,...p}=a;return{timestamp:i.timestamp,action:i.type.replace("memory.",""),data:p,author:u}}):[]}catch(s){return console.error(`Memory read error: ${s instanceof Error?s.message:String(s)}`),[]}}async clear(t){try{let e=await B.getProjectId(t);if(!e)return;E.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 E.query(t,"SELECT type, data, timestamp FROM events WHERE type LIKE 'memory.%' ORDER BY id DESC LIMIT ?",e).reverse().map(s=>{let o=JSON.parse(s.data);return{timestamp:s.timestamp,action:s.type.replace("memory.",""),...o}})}catch(r){return console.error(`Memory read error: ${r instanceof Error?r.message:String(r)}`),[]}}async capEntries(t){try{let r=E.get(t,"SELECT COUNT(*) as cnt FROM events WHERE type LIKE 'memory.%'")?.cnt??0;if(r<=ot.MEMORY_MAX_ENTRIES)return 0;let s=r-ot.MEMORY_MAX_ENTRIES,o=E.query(t,"SELECT id, type, data, timestamp FROM events WHERE type LIKE 'memory.%' ORDER BY id ASC LIMIT ?",s);K.archiveMany(t,o.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 i=o[o.length-1]?.id;return i!==void 0&&E.run(t,"DELETE FROM events WHERE type LIKE 'memory.%' AND id <= ?",i),s}catch(e){return console.error(`Memory cap error: ${e instanceof Error?e.message:String(e)}`),0}}},Rr=new se;var Ar="memory.",ne="remember.",oe=`${Ar}${ne}`,dc=`${Ar}task.tagged`;var Nr=["fact","decision","learning","gotcha","pattern","anti-pattern","shipped","inbox","todo","idea","insight","question","source","person"];var _n=25,Pn=4,Rn=100;function Cr(n,t){try{return JSON.parse(n)}catch{return t}}c(Cr,"safeJson");function An(n){let t=n.type.slice(oe.length),e=Cr(n.data,{});return{id:`mem_${n.id}`,type:t,content:e.content??"",tags:e.tags??{},rememberedAt:n.timestamp,source:e.source,provenance:e.provenance??"declared"}}c(An,"rowToEntry");function Nn(n){let t=n.data?Cr(n.data,{}):{},e=t.tags??{};return n.type&&(e.type=n.type),{id:`ship_${n.id}`,type:"shipped",content:n.name,tags:e,rememberedAt:n.shipped_at,source:t.taskId,provenance:"extracted"}}c(Nn,"shippedRowToEntry");function Cn(n,t){let e=t.toLowerCase();if(n.content.toLowerCase().includes(e))return!0;for(let r of Object.values(n.tags))if(r.toLowerCase().includes(e))return!0;return!1}c(Cn,"matchesTopic");function In(n,t){for(let[e,r]of Object.entries(t))if(n.tags[e]!==r)return!1;return!0}c(In,"matchesTags");var q={async remember(n,t){await Rr.log(n,`${ne}${t.type}`,{content:t.content,tags:t.tags??{},source:t.source,provenance:t.provenance??"declared"})},recall(n,t={}){let e=t.limit??_n,r=Math.max(e*Pn,Rn),s=E.query(n,"SELECT id, type, data, timestamp FROM events WHERE type LIKE ? ORDER BY id DESC LIMIT ?",`${oe}%`,r),o=E.query(n,"SELECT id, name, type, shipped_at, data FROM shipped_features ORDER BY shipped_at DESC LIMIT ?",r),i=[...s.map(An),...o.map(Nn)];if(t.types&&t.types.length>0){let a=new Set(t.types);i=i.filter(u=>a.has(u.type))}return t.tags&&(i=i.filter(a=>In(a,t.tags??{}))),t.topic&&(i=i.filter(a=>Cn(a,t.topic))),i.sort((a,u)=>u.rememberedAt.localeCompare(a.rememberedAt)),i.slice(0,e)},similar(n,t,e=10){let r=t.toLowerCase().split(/[^a-z0-9]+/).filter(i=>i.length>3);return r.length===0?[]:q.recall(n,{limit:200}).map(i=>{let a=`${i.content} ${Object.values(i.tags).join(" ")}`.toLowerCase(),u=r.reduce((p,m)=>a.includes(m)?p+1:p,0);return{entry:i,hits:u}}).filter(i=>i.hits>0).sort((i,a)=>a.hits-i.hits).slice(0,e).map(i=>i.entry)}};function it(n){if(n.length===0)return"> No matching memory entries.";let t=new Map;for(let o of n){let i=t.get(o.type)??[];i.push(o),t.set(o.type,i)}let e=["decision","learning","anti-pattern","gotcha","pattern","fact","shipped"],r=[],s={declared:"DECL",extracted:"EXTR",inferred:"INFR",ambiguous:"AMBG"};for(let o of e){let i=t.get(o);if(!(!i||i.length===0)){r.push(`### ${o.toUpperCase()}`);for(let a of i){let u=Object.entries(a.tags).map(([d,g])=>`${d}=${g}`).join(" "),p=u?` _(${u})_`:"",m=s[a.provenance];r.push(`- \`${m}\` [${a.id}] ${a.content}${p}`)}r.push("")}}return r.join(`
|
|
523
|
-
`).trim()}c(it,"formatMemoryMd");var Dn=[{name:"sk-\u2026 token",re:/\bsk-[A-Za-z0-9_-]{16,}/},{name:"GitHub PAT",re:/\bghp_[A-Za-z0-9]{30,}/},{name:"GitHub server PAT",re:/\bghs_[A-Za-z0-9]{30,}/},{name:"AWS access key",re:/\bAKIA[0-9A-Z]{16}\b/},{name:"Slack token",re:/\bxox[abps]-[A-Za-z0-9-]{10,}/},{name:"bearer JWT-ish",re:/\beyJ[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}\b/}];function Ir(n){let t=[];for(let{name:e,re:r}of Dn)r.test(n)&&t.push(e);return t}c(Ir,"scanForSecrets");var Dr=`Base types: ${Nr.join(", ")}. Any lowercase identifier is accepted (e.g. "recipe", "okr").`;function Lr(n){let t=n;t.tool("prjct_mem_save",`Save a memory entry. ${Dr} Secret-like content is refused unless force=true.`,{projectPath:v.string().describe("Project directory path"),type:v.string().describe("Memory type (fact/decision/learning/... or user-defined)"),content:v.string().describe("The memory content. Freeform text."),tags:v.record(v.string(),v.string()).optional().describe('Key:value tags (e.g. {domain: "auth"})'),source:v.string().optional().describe("Task id this memory came from, if any"),force:v.boolean().optional().describe("Bypass the secret-like-content refusal. Default false.")},S("prjct_mem_save",async e=>{await P(e.projectPath);let r=e.type.toLowerCase().trim();if(!r||!/^[a-z][a-z0-9-]*$/.test(r))return{content:[{type:"text",text:`Invalid type '${e.type}'. Lowercase letters + dashes only. ${Dr}`}]};let s=Ir(e.content);return s.length>0&&!e.force?{content:[{type:"text",text:`Refused \u2014 content looks like a secret (${s.join(", ")}). Re-call with force=true if intentional.`}]}:(await q.remember(e.projectPath,{type:r,content:e.content,tags:e.tags??{},source:e.source}),{content:[{type:"text",text:`Saved ${r}: ${e.content.slice(0,80)}`}]})})),t.tool("prjct_mem_list","Recall memory entries. Optional filters: topic (keyword across content + tag values), types, tags, limit.",{projectPath:v.string().describe("Project directory path"),topic:v.string().optional().describe("Keyword to match over content + tag values"),types:v.array(v.string()).optional().describe("Restrict to these types"),tags:v.record(v.string(),v.string()).optional().describe("Require exact match on these k:v pairs"),limit:v.number().optional().default(25).describe("Max entries (default 25)")},S("prjct_mem_list",async e=>{let r=await P(e.projectPath),s=q.recall(r,{topic:e.topic,types:e.types,tags:e.tags,limit:e.limit});return{content:[{type:"text",text:it(s)}]}})),t.tool("prjct_mem_similar","Find memory entries similar to a free-text description. Keyword-based, best-effort.",{projectPath:v.string().describe("Project directory path"),description:v.string().describe("Free-text description to find similar memories for"),limit:v.number().optional().default(10).describe("Max results (default 10)")},S("prjct_mem_similar",async e=>{let r=await P(e.projectPath),s=q.similar(r,e.description,e.limit);return s.length===0?{content:[{type:"text",text:"No similar memories found."}]}:{content:[{type:"text",text:it(s)}]}})),t.tool("prjct_mem_forget","Remove a memory entry by id. Ids are stable \u2014 pull them from `prjct_mem_list`.",{projectPath:v.string().describe("Project directory path"),id:v.string().describe('Memory id (e.g. "mem_42" or "ship_7")')},S("prjct_mem_forget",async e=>({content:[{type:"text",text:"Forget is not implemented in the projectMemory API yet. Entries persist event-sourced \u2014 filter them out client-side, or drop the underlying event manually."}]})))}c(Lr,"registerMemoryTools");import{z as ce}from"zod";var ie=class{static{c(this,"LLMAnalysisStorage")}save(t,e){let r=T.getDb(t),s=f();r.transaction(()=>{r.prepare("UPDATE llm_analysis SET status = 'superseded', superseded_at = ? WHERE status = 'active'").run(s),r.prepare("INSERT INTO llm_analysis (commit_hash, status, analysis, analyzed_at) VALUES (?, ?, ?, ?)").run(e.commitHash??null,"active",JSON.stringify(e),e.analyzedAt)})()}getActive(t){let e=T.get(t,"SELECT analysis FROM llm_analysis WHERE status = 'active' LIMIT 1");return e?JSON.parse(e.analysis):null}getActiveSummary(t){let e=this.getActive(t);return e?{commitHash:e.commitHash,architectureStyle:e.architecture.style,patternCount:e.patterns.length,antiPatternCount:e.antiPatterns.length,analyzedAt:e.analyzedAt}:null}isCurrent(t,e){return e?T.get(t,"SELECT commit_hash FROM llm_analysis WHERE status = 'active' LIMIT 1")?.commit_hash===e:!1}getHistory(t,e=10){return T.query(t,"SELECT id, commit_hash, status, analyzed_at, analysis FROM llm_analysis ORDER BY id DESC LIMIT ?",e).map(s=>{let o=JSON.parse(s.analysis);return{id:s.id,commitHash:s.commit_hash,status:s.status,analyzedAt:s.analyzed_at,patternCount:o.patterns.length}})}},Ln=new ie,Or=Ln;var jr={critical:0,high:1,medium:2,low:3},Mr={active:0,previously_active:1,backlog:2};function Fr(n){return[...n].sort((t,e)=>{let r=Mr[t.section]-Mr[e.section];return r!==0?r:jr[t.priority]-jr[e.priority]})}c(Fr,"sortBySectionAndPriority");var ae=class extends Q{static{c(this,"QueueStorage")}constructor(){super("queue.json",Tr)}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(r=>r.section==="active"&&!r.completed)}async getBacklog(t){return(await this.read(t)).tasks.filter(r=>r.section==="backlog"&&!r.completed)}async getNextTask(t){let e=await this.getActiveTasks(t);return Fr(e)[0]||null}async addTask(t,e){let r={...e,id:$(),createdAt:f(),completed:!1};return await this.update(t,s=>({tasks:[...s.tasks,r],lastUpdated:f()})),await this.publishEvent(t,"queue.task_added",{taskId:r.id,description:r.description,priority:r.priority,section:r.section}),r}async addTasks(t,e){let r=f(),s=e.map(o=>({...o,id:$(),createdAt:r,completed:!1}));return await this.update(t,o=>({tasks:[...o.tasks,...s],lastUpdated:r})),await this.publishEvent(t,"queue.tasks_added",{count:s.length,tasks:s.map(o=>({id:o.id,description:o.description}))}),s}async removeTask(t,e){await this.update(t,r=>({tasks:r.tasks.filter(s=>s.id!==e),lastUpdated:f()})),await this.publishEvent(t,"queue.task_removed",{taskId:e})}async completeTask(t,e){let r=null;if(await this.update(t,s=>({tasks:s.tasks.map(i=>i.id===e?(r={...i,completed:!0,completedAt:f()},r):i),lastUpdated:f()})),r){let s=r;await this.publishEvent(t,"queue.task_completed",{taskId:e,description:s.description,completedAt:s.completedAt})}return r}async moveToSection(t,e,r){await this.update(t,s=>({tasks:s.tasks.map(o=>o.id===e?{...o,section:r}:o),lastUpdated:f()}))}async setPriority(t,e,r){await this.update(t,s=>({tasks:s.tasks.map(o=>o.id===e?{...o,priority:r}:o),lastUpdated:f()}))}async getTask(t,e){return(await this.read(t)).tasks.find(s=>s.id===e)||null}async updateTask(t,e,r){let s=null;return await this.update(t,o=>({tasks:o.tasks.map(i=>i.id===e?(s={...i,...r},s):i),lastUpdated:f()})),s&&await this.publishEvent(t,"queue.task_updated",{taskId:e}),s}async clearCompleted(t){let r=(await this.read(t)).tasks.filter(s=>s.completed).length;return await this.update(t,s=>({tasks:s.tasks.filter(o=>!o.completed),lastUpdated:f()})),r}async removeStaleCompleted(t){let e=await this.read(t),r=Ee(ot.QUEUE_COMPLETED_DAYS),s=e.tasks.filter(i=>i.completed&&i.completedAt&&new Date(i.completedAt)<r);if(s.length===0)return 0;K.archiveMany(t,s.map(i=>({entityType:"queue_task",entityId:i.id,entityData:i,summary:i.description,reason:"age"})));let o=new Set(s.map(i=>i.id));return await this.update(t,i=>({tasks:i.tasks.filter(a=>!o.has(a.id)),lastUpdated:f()})),await this.publishEvent(t,"queue.stale_removed",{count:s.length}),s.length}},Ur=new ae;function Xr(n){let t=n;t.tool("prjct_task_status","Current task, duration, subtasks, and queue",{projectPath:ce.string().describe("Project directory path")},S("prjct_task_status",async e=>{let r=await P(e.projectPath),s=await Z.getCurrentTask(r),o=await Ur.getActiveTasks(r),i=[];if(s?(i.push(`## Active Task
|
|
523
|
+
`).trim()}c(it,"formatMemoryMd");var Dn=[{name:"sk-\u2026 token",re:/\bsk-[A-Za-z0-9_-]{16,}/},{name:"GitHub PAT",re:/\bghp_[A-Za-z0-9]{30,}/},{name:"GitHub server PAT",re:/\bghs_[A-Za-z0-9]{30,}/},{name:"AWS access key",re:/\bAKIA[0-9A-Z]{16}\b/},{name:"Slack token",re:/\bxox[abps]-[A-Za-z0-9-]{10,}/},{name:"bearer JWT-ish",re:/\beyJ[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}\b/}];function Ir(n){let t=[];for(let{name:e,re:r}of Dn)r.test(n)&&t.push(e);return t}c(Ir,"scanForSecrets");var Dr=`Base types: ${Nr.join(", ")}. Any lowercase identifier is accepted (e.g. "recipe", "okr").`;function Lr(n){let t=n;t.tool("prjct_mem_save",`Save a memory entry. ${Dr} Secret-like content is refused unless force=true.`,{projectPath:v.string().describe("Project directory path"),type:v.string().describe("Memory type (fact/decision/learning/... or user-defined)"),content:v.string().describe("The memory content. Freeform text."),tags:v.record(v.string(),v.string()).optional().describe('Key:value tags (e.g. {domain: "auth"})'),source:v.string().optional().describe("Task id this memory came from, if any"),force:v.boolean().optional().describe("Bypass the secret-like-content refusal. Default false.")},S("prjct_mem_save",async e=>{await P(e.projectPath);let r=e.type.toLowerCase().trim();if(!r||!/^[a-z][a-z0-9-]*$/.test(r))return{content:[{type:"text",text:`Invalid type '${e.type}'. Lowercase letters + dashes only. ${Dr}`}]};let s=Ir(e.content);return s.length>0&&!e.force?{content:[{type:"text",text:`Refused \u2014 content looks like a secret (${s.join(", ")}). Re-call with force=true if intentional.`}]}:(await q.remember(e.projectPath,{type:r,content:e.content,tags:e.tags??{},source:e.source}),{content:[{type:"text",text:`Saved ${r}: ${e.content.slice(0,80)}`}]})})),t.tool("prjct_mem_list","Recall memory entries. Optional filters: topic (keyword across content + tag values), types, tags, limit.",{projectPath:v.string().describe("Project directory path"),topic:v.string().optional().describe("Keyword to match over content + tag values"),types:v.array(v.string()).optional().describe("Restrict to these types"),tags:v.record(v.string(),v.string()).optional().describe("Require exact match on these k:v pairs"),limit:v.number().optional().default(25).describe("Max entries (default 25)")},S("prjct_mem_list",async e=>{let r=await P(e.projectPath),s=q.recall(r,{topic:e.topic,types:e.types,tags:e.tags,limit:e.limit});return{content:[{type:"text",text:it(s)}]}})),t.tool("prjct_mem_similar","Find memory entries similar to a free-text description. Keyword-based, best-effort.",{projectPath:v.string().describe("Project directory path"),description:v.string().describe("Free-text description to find similar memories for"),limit:v.number().optional().default(10).describe("Max results (default 10)")},S("prjct_mem_similar",async e=>{let r=await P(e.projectPath),s=q.similar(r,e.description,e.limit);return s.length===0?{content:[{type:"text",text:"No similar memories found."}]}:{content:[{type:"text",text:it(s)}]}})),t.tool("prjct_mem_forget","Remove a memory entry by id. Ids are stable \u2014 pull them from `prjct_mem_list`.",{projectPath:v.string().describe("Project directory path"),id:v.string().describe('Memory id (e.g. "mem_42" or "ship_7")')},S("prjct_mem_forget",async e=>({content:[{type:"text",text:"Forget is not implemented in the projectMemory API yet. Entries persist event-sourced \u2014 filter them out client-side, or drop the underlying event manually."}]})))}c(Lr,"registerMemoryTools");import{z as ce}from"zod";var ie=class{static{c(this,"LLMAnalysisStorage")}save(t,e){let r=T.getDb(t),s=f();r.transaction(()=>{r.prepare("UPDATE llm_analysis SET status = 'superseded', superseded_at = ? WHERE status = 'active'").run(s),r.prepare("INSERT INTO llm_analysis (commit_hash, status, analysis, analyzed_at) VALUES (?, ?, ?, ?)").run(e.commitHash??null,"active",JSON.stringify(e),e.analyzedAt)})()}getActive(t){let e=T.get(t,"SELECT analysis FROM llm_analysis WHERE status = 'active' LIMIT 1");return e?JSON.parse(e.analysis):null}getActiveSummary(t){let e=this.getActive(t);return e?{commitHash:e.commitHash,architectureStyle:e.architecture.style,patternCount:e.patterns.length,antiPatternCount:e.antiPatterns.length,analyzedAt:e.analyzedAt}:null}isCurrent(t,e){return e?T.get(t,"SELECT commit_hash FROM llm_analysis WHERE status = 'active' LIMIT 1")?.commit_hash===e:!1}getAllFull(t){return T.query(t,"SELECT id, commit_hash, status, analyzed_at, superseded_at, analysis FROM llm_analysis ORDER BY id DESC").map(r=>({id:r.id,status:r.status,commitHash:r.commit_hash,analyzedAt:r.analyzed_at,supersededAt:r.superseded_at,analysis:JSON.parse(r.analysis)}))}getHistory(t,e=10){return T.query(t,"SELECT id, commit_hash, status, analyzed_at, analysis FROM llm_analysis ORDER BY id DESC LIMIT ?",e).map(s=>{let o=JSON.parse(s.analysis);return{id:s.id,commitHash:s.commit_hash,status:s.status,analyzedAt:s.analyzed_at,patternCount:o.patterns.length}})}},Ln=new ie,Or=Ln;var jr={critical:0,high:1,medium:2,low:3},Mr={active:0,previously_active:1,backlog:2};function Fr(n){return[...n].sort((t,e)=>{let r=Mr[t.section]-Mr[e.section];return r!==0?r:jr[t.priority]-jr[e.priority]})}c(Fr,"sortBySectionAndPriority");var ae=class extends Q{static{c(this,"QueueStorage")}constructor(){super("queue.json",Tr)}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(r=>r.section==="active"&&!r.completed)}async getBacklog(t){return(await this.read(t)).tasks.filter(r=>r.section==="backlog"&&!r.completed)}async getNextTask(t){let e=await this.getActiveTasks(t);return Fr(e)[0]||null}async addTask(t,e){let r={...e,id:$(),createdAt:f(),completed:!1};return await this.update(t,s=>({tasks:[...s.tasks,r],lastUpdated:f()})),await this.publishEvent(t,"queue.task_added",{taskId:r.id,description:r.description,priority:r.priority,section:r.section}),r}async addTasks(t,e){let r=f(),s=e.map(o=>({...o,id:$(),createdAt:r,completed:!1}));return await this.update(t,o=>({tasks:[...o.tasks,...s],lastUpdated:r})),await this.publishEvent(t,"queue.tasks_added",{count:s.length,tasks:s.map(o=>({id:o.id,description:o.description}))}),s}async removeTask(t,e){await this.update(t,r=>({tasks:r.tasks.filter(s=>s.id!==e),lastUpdated:f()})),await this.publishEvent(t,"queue.task_removed",{taskId:e})}async completeTask(t,e){let r=null;if(await this.update(t,s=>({tasks:s.tasks.map(i=>i.id===e?(r={...i,completed:!0,completedAt:f()},r):i),lastUpdated:f()})),r){let s=r;await this.publishEvent(t,"queue.task_completed",{taskId:e,description:s.description,completedAt:s.completedAt})}return r}async moveToSection(t,e,r){await this.update(t,s=>({tasks:s.tasks.map(o=>o.id===e?{...o,section:r}:o),lastUpdated:f()}))}async setPriority(t,e,r){await this.update(t,s=>({tasks:s.tasks.map(o=>o.id===e?{...o,priority:r}:o),lastUpdated:f()}))}async getTask(t,e){return(await this.read(t)).tasks.find(s=>s.id===e)||null}async updateTask(t,e,r){let s=null;return await this.update(t,o=>({tasks:o.tasks.map(i=>i.id===e?(s={...i,...r},s):i),lastUpdated:f()})),s&&await this.publishEvent(t,"queue.task_updated",{taskId:e}),s}async clearCompleted(t){let r=(await this.read(t)).tasks.filter(s=>s.completed).length;return await this.update(t,s=>({tasks:s.tasks.filter(o=>!o.completed),lastUpdated:f()})),r}async removeStaleCompleted(t){let e=await this.read(t),r=Ee(ot.QUEUE_COMPLETED_DAYS),s=e.tasks.filter(i=>i.completed&&i.completedAt&&new Date(i.completedAt)<r);if(s.length===0)return 0;K.archiveMany(t,s.map(i=>({entityType:"queue_task",entityId:i.id,entityData:i,summary:i.description,reason:"age"})));let o=new Set(s.map(i=>i.id));return await this.update(t,i=>({tasks:i.tasks.filter(a=>!o.has(a.id)),lastUpdated:f()})),await this.publishEvent(t,"queue.stale_removed",{count:s.length}),s.length}},Ur=new ae;function Xr(n){let t=n;t.tool("prjct_task_status","Current task, duration, subtasks, and queue",{projectPath:ce.string().describe("Project directory path")},S("prjct_task_status",async e=>{let r=await P(e.projectPath),s=await Z.getCurrentTask(r),o=await Ur.getActiveTasks(r),i=[];if(s?(i.push(`## Active Task
|
|
524
524
|
**${s.description}**`),s.branch&&i.push(`Branch: ${s.branch}`),i.push(`Started: ${s.startedAt}`)):i.push("No active task."),o.length>0){i.push(`
|
|
525
525
|
## Queue (${o.length} tasks)`);for(let a of o.slice(0,10))i.push(`- ${a.description} [${a.priority||"medium"}]`)}return{content:[{type:"text",text:i.join(`
|
|
526
526
|
`)}]}})),t.tool("prjct_analysis","LLM analysis: stack, patterns, anti-patterns, conventions",{projectPath:ce.string().describe("Project directory path")},S("prjct_analysis",async e=>{let r=await P(e.projectPath),s=Or.getActive(r);if(!s)return{content:[{type:"text",text:"No analysis available. Run `prjct sync`."}]};let o=["## Project Analysis"];if(s.stack&&(o.push(`
|