prjct-cli 1.44.5 → 1.45.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.
@@ -3,7 +3,7 @@ import{connect}from"node:net";import{existsSync}from"node:fs";import{randomUUID}
3
3
  const sockPath=homedir()+"/.prjct-cli/run/daemon.sock";
4
4
  const args=process.argv.slice(2);
5
5
  const cmd=args.find(a=>!a.startsWith("-"));
6
- const skip=new Set(["daemon","start","setup","update","dev","web","serve","context","hooks","doctor","uninstall","watch","linear","help","-h","--help","version","-v","--version"]);
6
+ const skip=new Set(["daemon","start","setup","update","dev","web","serve","context","hooks","doctor","uninstall","watch","linear","jira","help","-h","--help","version","-v","--version"]);
7
7
  if(cmd&&!skip.has(cmd)&&process.env.PRJCT_NO_DAEMON!=="1"&&existsSync(sockPath)){
8
8
  const cArgs=[],cOpts={};
9
9
  for(let i=0;i<args.length;i++){const a=args[i];if(a.startsWith("--")){const r=a.slice(2);if(r.includes("=")){const e=r.indexOf("=");cOpts[r.slice(0,e)]=r.slice(e+1)}else if(i+1<args.length&&!args[i+1].startsWith("--")){cOpts[r]=args[++i]}else{cOpts[r]=true}}else if(a.startsWith("-")&&a.length===2){cOpts[a.slice(1)]=true}else if(i>0){cArgs.push(a)}}
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire as __createRequire } from 'module';
3
+ import { fileURLToPath as __fileURLToPath } from 'url';
4
+ import { dirname as __pathDirname } from 'path';
5
+ var require = __createRequire(import.meta.url);
6
+ var __filename = __fileURLToPath(import.meta.url);
7
+ var __dirname = __pathDirname(__filename);
8
+ var S=Object.defineProperty;var t=(e,r)=>S(e,"name",{value:r,configurable:!0});function c(e){return e instanceof Error?e.message:typeof e=="string"?e:"Unknown error"}t(c,"getErrorMessage");import l from"node:fs/promises";import M from"node:os";import f from"node:path";var h={linear:{command:"npx",args:["-y","mcp-remote","https://mcp.linear.app/mcp"],description:"Linear MCP server (OAuth)"},jira:{command:"npx",args:["-y","mcp-remote","https://mcp.atlassian.com/v1/mcp"],description:"Atlassian MCP server for Jira (OAuth)"}};function i(){return process.env.PRJCT_TEST_MODE==="1"?f.join(M.tmpdir(),"prjct-context7-test","mcp.json"):f.join(M.homedir(),".claude","mcp.json")}t(i,"getClaudeMcpConfigPath");async function v(e=i()){try{let r=await l.readFile(e,"utf-8");return JSON.parse(r)}catch(r){let n=c(r).toLowerCase();if(n.includes("no such file")||n.includes("enoent"))return{};throw new Error(`Failed to read MCP config at ${e}: ${c(r)}`)}}t(v,"readMcpConfig");async function k(e,r=i()){await l.mkdir(f.dirname(r),{recursive:!0}),await l.writeFile(r,JSON.stringify(e,null,2),"utf-8")}t(k,"writeMcpConfig");async function y(e,r,n=i()){let s=await v(n),d={...s.mcpServers||{}},a=d[e];d[e]=r,s.mcpServers=d;let j=JSON.stringify(a)!==JSON.stringify(r);return await k(s,n),{path:n,changed:j}}t(y,"upsertMcpServer");async function u(e,r=i()){return!!(await v(r)).mcpServers?.[e]}t(u,"hasMcpServer");var g=process.argv.slice(2),w=g.indexOf("--json"),P=w!==-1;P&&g.splice(w,1);var E=g.indexOf("--md");E!==-1&&g.splice(E,1);var[m,...C]=g;function o(e){if(P){console.log(JSON.stringify(e,null,2));return}if(typeof e=="string"){console.log(e);return}console.log(JSON.stringify(e,null,2))}t(o,"output");function p(e,r=1){console.error(P?JSON.stringify({error:e}):`Error: ${e}`),process.exit(r)}t(p,"error");async function b(){let e=await y("jira",h.jira);o({success:!0,provider:"jira",mode:"mcp",path:e.path,updated:e.changed,nextSteps:["Open your MCP-enabled AI client.","Run any Jira operation to complete OAuth authorization when prompted."]})}t(b,"setup");async function x(){let e=i(),r=await u("jira",e);o({provider:"jira",mode:"mcp",configured:r,path:e,hint:r?"Jira MCP is configured. OAuth happens inside your AI client.":"Run `prjct jira setup` to configure Jira MCP."})}t(x,"status");async function J(e,r,n){let s=i();await u("jira",s)||p("Jira MCP is not configured. Run `prjct jira setup` first.");let a={success:!0,provider:"jira",mode:"mcp",delegated:!0,command:e,args:r,hint:n?.hint??"Run this operation using Jira MCP tools in your current AI client session.",nextSteps:["Open your MCP-enabled AI client/session.",`Execute the Jira MCP operation for "${e}".`]};n?.jql&&(a.jql=n.jql),n?.scope&&(a.scope=n.scope),o(a)}t(J,"runMcpOperation");async function O(e){let r=i();await u("jira",r)||p("Jira MCP is not configured. Run `prjct jira setup` first."),o({success:!0,provider:"jira",mode:"mcp",delegated:!0,command:"sprint",scope:"active_sprint",args:e,jql:"sprint = currentSprint() AND assignee = currentUser() ORDER BY priority DESC",hint:"Fetch your issues in the active sprint via Jira MCP tools.",nextSteps:["Use the Jira MCP search tool with the JQL above to list your active sprint issues.","Issues returned include sprint metadata (sprint name, start/end dates)."]})}t(O,"sprintOperation");async function R(e){let r=i();await u("jira",r)||p("Jira MCP is not configured. Run `prjct jira setup` first."),o({success:!0,provider:"jira",mode:"mcp",delegated:!0,command:"backlog",scope:"backlog",args:e,jql:"sprint is EMPTY AND assignee = currentUser() AND statusCategory != Done ORDER BY priority DESC",hint:"Fetch your backlog issues (not in any sprint) via Jira MCP tools.",nextSteps:["Use the Jira MCP search tool with the JQL above to list your backlog issues.","Backlog issues have no sprint assigned \u2014 differentiate from sprint issues by the sprint field being empty."]})}t(R,"backlogOperation");async function D(){try{switch(m){case"setup":await b();break;case"status":await x();break;case"help":case"--help":case"-h":case void 0:o({usage:"prjct jira <command>",commands:{setup:"Configure Jira MCP server",status:"Check Jira MCP configuration",sprint:"List your issues in the active sprint (MCP)",backlog:"List your backlog issues not in any sprint (MCP)",sync:"Delegate issue sync via MCP tools",list:"Delegate issue listing via MCP tools",get:"Delegate issue retrieval via MCP tools",create:"Delegate issue creation via MCP tools",update:"Delegate issue update via MCP tools",start:"Delegate status transition to in-progress via MCP tools",done:"Delegate status transition to done via MCP tools",transition:"Delegate workflow transition via MCP tools"},note:"Jira is MCP-only. sprint/backlog provide JQL for your AI client MCP session."});break;case"sprint":await O(C);break;case"backlog":await R(C);break;case"sync":case"start":case"done":case"list":case"get":case"create":case"update":case"transition":case"comment":case"projects":case"boards":await J(m,C);break;default:p(`Unknown command: ${m}. Use --help to see available commands.`)}}catch(e){p(c(e))}}t(D,"main");D();
@@ -5,347 +5,4 @@ import { dirname as __pathDirname } from 'path';
5
5
  var require = __createRequire(import.meta.url);
6
6
  var __filename = __fileURLToPath(import.meta.url);
7
7
  var __dirname = __pathDirname(__filename);
8
- var Te=Object.defineProperty;var kr=Object.getOwnPropertyDescriptor;var wr=Object.getOwnPropertyNames;var vr=Object.prototype.hasOwnProperty;var o=(n,e)=>Te(n,"name",{value:e,configurable:!0}),St=(n=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(n,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):n)(function(n){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+n+'" is not supported')});var ee=(n,e)=>()=>(n&&(e=n(n=0)),e);var Et=(n,e)=>{for(var t in e)Te(n,t,{get:e[t],enumerable:!0})},Ar=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of wr(e))!vr.call(n,s)&&s!==t&&Te(n,s,{get:()=>e[s],enumerable:!(r=kr(e,s))||r.enumerable});return n};var Xe=n=>Ar(Te({},"__esModule",{value:!0}),n);function Tt(n){return n instanceof Error&&"code"in n}function q(n){return Tt(n)&&n.code==="ENOENT"}function O(n){return n instanceof Error?n.message:typeof n=="string"?n:"Unknown error"}var X=ee(()=>{"use strict";o(Tt,"isNodeError");o(q,"isNotFoundError");o(O,"getErrorMessage")});var xt={};Et(xt,{deleteCredential:()=>_r,getCredential:()=>ie,getCredentialWithSource:()=>Nr,hasCredential:()=>Lr,setCredential:()=>Dr});import{exec as Cr}from"node:child_process";import{promisify as Rr}from"node:util";async function Dr(n,e){if(process.platform!=="darwin")return console.warn("[keychain] macOS Keychain only available on macOS"),!1;try{return await ue(`security delete-generic-password -s "${pe}" -a "${n}" 2>/dev/null || true`),await ue(`security add-generic-password -s "${pe}" -a "${n}" -w "${e}"`),!0}catch(t){return console.error("[keychain] Failed to store credential:",O(t)),!1}}async function ie(n){if(process.platform!=="darwin")return Ke(n);try{let{stdout:e}=await ue(`security find-generic-password -s "${pe}" -a "${n}" -w 2>/dev/null`);return e.trim()||null}catch{return Ke(n)}}async function _r(n){if(process.platform!=="darwin")return!1;try{return await ue(`security delete-generic-password -s "${pe}" -a "${n}" 2>/dev/null`),!0}catch{return!1}}async function Lr(n){let e=await ie(n);return e!==null&&e.length>0}function Ke(n){let t={"linear-api-key":"LINEAR_API_KEY","jira-api-token":"JIRA_API_TOKEN"}[n];return process.env[t]||null}async function Nr(n){if(process.platform==="darwin")try{let{stdout:t}=await ue(`security find-generic-password -s "${pe}" -a "${n}" -w 2>/dev/null`),r=t.trim();if(r)return{value:r,source:"keychain"}}catch{}let e=Ke(n);return e?{value:e,source:"env"}:{value:null,source:"none"}}var ue,pe,be=ee(()=>{"use strict";X();ue=Rr(Cr),pe="prjct-cli";o(Dr,"setCredential");o(ie,"getCredential");o(_r,"deleteCredential");o(Lr,"hasCredential");o(Ke,"getEnvFallback");o(Nr,"getCredentialWithSource")});import Ct from"node:fs/promises";async function Rt(n,e){let t;try{t=await Ct.readFile(n,"utf-8")}catch(i){if(q(i))return null;throw i}let r;try{r=JSON.parse(t)}catch{return await vt(n,t),At(n,"Malformed JSON"),null}let s=e.safeParse(r);return s.success?r:(await vt(n,t),At(n,Gr(s.error)),null)}async function vt(n,e){let t=`${n}.backup`;try{await Ct.writeFile(t,e,"utf-8")}catch{}}function At(n,e){console.error(`[prjct] Warning: Corrupted storage file: ${n}`),console.error(`[prjct] Reason: ${e}`),console.error("[prjct] A .backup file has been created. Returning defaults.")}function Gr(n){return n.issues.slice(0,3).map(e=>`${e.path.join(".")}: ${e.message}`).join("; ")}var Dt=ee(()=>{"use strict";X();o(Rt,"safeRead");o(vt,"createBackup");o(At,"logCorruption");o(Gr,"formatZodError")});import de from"node:fs/promises";async function ke(n,e=null,t){if(t)return await Rt(n,t)??e;try{let r=await de.readFile(n,"utf-8");return JSON.parse(r)}catch(r){if(q(r))return e;throw r}}async function we(n,e,t=2){let r=JSON.stringify(e,null,t);await de.writeFile(n,r,"utf-8")}async function k(n){try{return await de.access(n),!0}catch(e){if(q(e))return!1;throw e}}async function Be(n){try{return(await de.stat(n)).isDirectory()}catch(e){if(q(e))return!1;throw e}}async function V(n){await de.mkdir(n,{recursive:!0})}var me=ee(()=>{"use strict";Dt();X();o(ke,"readJson");o(we,"writeJson");o(k,"fileExists");o(Be,"dirExists");o(V,"ensureDir")});import{z as J}from"zod";function Lt(n,e){let t=n.split(".").map(Number),r=e.split(".").map(Number);for(let s=0;s<3;s++){let i=t[s]??0,u=r[s]??0;if(i<u)return-1;if(i>u)return 1}return 0}var Ri,Di,_i,oe,Li,ge=ee(()=>{"use strict";Ri=J.enum(["opus","sonnet","haiku"]),Di=J.enum(["2.5-pro","2.5-flash","2.0-flash"]),_i=J.string().min(1),oe=J.object({provider:J.string(),model:J.string(),cliVersion:J.string().optional(),recordedAt:J.string()}),Li=J.object({preferredModel:J.string().optional(),lastAnalysisModel:oe.optional()});o(Lt,"compareSemver")});import qe from"node:fs/promises";import Xr from"node:os";import Nt from"node:path";async function Mt(){try{let n=await qe.readFile(jt,"utf-8"),e=JSON.parse(n);return!e.timestamp||!e.detection||Date.now()-new Date(e.timestamp).getTime()>Jr?null:e.detection}catch{return null}}async function Ft(n){let e={timestamp:new Date().toISOString(),detection:n};await qe.mkdir(Ot,{recursive:!0}),await qe.writeFile(jt,JSON.stringify(e,null,2))}var Ot,jt,Jr,Ut=ee(()=>{"use strict";Ot=Nt.join(Xr.homedir(),".prjct-cli","cache"),jt=Nt.join(Ot,"providers.json"),Jr=600*1e3;o(Mt,"readProviderCache");o(Ft,"writeProviderCache")});var Ce={};Et(Ce,{AntigravityProvider:()=>We,ClaudeProvider:()=>ve,CodexProvider:()=>Qe,CursorProvider:()=>Gt,GeminiProvider:()=>Ye,Providers:()=>z,WindsurfProvider:()=>Xt,detectAllProviders:()=>Ze,detectAntigravity:()=>en,detectCodex:()=>qt,detectCursorProject:()=>Kt,detectProvider:()=>Ve,detectWindsurfProject:()=>Bt,getActiveProvider:()=>Yr,getCapabilities:()=>qr,getCommandsDir:()=>sn,getGlobalContextPath:()=>tn,getGlobalSettingsPath:()=>rn,getProjectCommandsPath:()=>on,getProviderBranding:()=>Ae,getSkillsPath:()=>nn,hasProviderConfig:()=>Wr,needsCursorRouterRegeneration:()=>Qr,needsWindsurfRouterRegeneration:()=>Zr,selectProvider:()=>an,validateCliVersion:()=>Ht});import{exec as Hr}from"node:child_process";import Y from"node:os";import w from"node:path";import{promisify as Kr}from"node:util";function qr(n,e){return{...Br[n],...e}}async function Jt(n){try{let{stdout:e}=await $t(`which ${n}`,{timeout:zt});return e.trim()}catch{return null}}async function Vr(n){try{let{stdout:e}=await $t(`${n} --version`,{timeout:zt}),t=e.match(/\d+\.\d+\.\d+/);return t?t[0]:e.trim()}catch{return null}}async function Ve(n){let e=z[n];if(!e.cliCommand)return{installed:!1};let t=await Jt(e.cliCommand);if(!t)return{installed:!1};let r=await Vr(e.cliCommand),s=Ht(n,r||void 0);return{installed:!0,version:r||void 0,path:t,versionWarning:s||void 0}}function Ht(n,e){let t=z[n];return!t.minCliVersion||!e?null:Lt(e,t.minCliVersion)<0?`\u26A0\uFE0F ${t.displayName} v${e} is below minimum v${t.minCliVersion}. Some features may not work correctly.`:null}async function Ze(n=!1){if(!n){let u=await Mt();if(u)return u}let[e,t,r]=await Promise.all([Ve("claude"),Ve("gemini"),qt()]),s={installed:r.installed},i={claude:e,gemini:t,codex:s};return await Ft(i).catch(()=>{}),i}async function Yr(n){if(n&&z[n])return z[n];let e=await Ze();return e.claude.installed&&!e.gemini.installed?ve:e.gemini.installed&&!e.claude.installed?Ye:ve}async function Wr(n){let e=z[n];return e.configDir?k(e.configDir):!1}function Ae(n){return{commitFooter:"Generated with [p/](https://www.prjct.app/)",signature:{claude:"\u26A1 prjct + Claude",gemini:"\u26A1 prjct + Gemini",cursor:"\u26A1 prjct + Cursor",antigravity:"\u26A1 prjct + Antigravity",windsurf:"\u26A1 prjct + Windsurf",codex:"\u26A1 prjct + Codex"}[n]||"\u26A1 prjct"}}async function Kt(n){let e=w.join(n,".cursor"),t=w.join(e,"rules"),r=w.join(t,"prjct.mdc"),[s,i]=await Promise.all([k(e),k(r)]);return{detected:s,routerInstalled:i,projectRoot:s?n:void 0}}async function Qr(n){let e=await Kt(n);return e.detected&&!e.routerInstalled}async function Bt(n){let e=w.join(n,".windsurf"),t=w.join(e,"rules"),r=w.join(t,"prjct.md"),[s,i]=await Promise.all([k(e),k(r)]);return{detected:s,routerInstalled:i,projectRoot:s?n:void 0}}async function Zr(n){let e=await Bt(n);return e.detected&&!e.routerInstalled}async function en(){let n=We.configDir;if(!n)return{installed:!1,skillInstalled:!1};let e=w.join(n,"skills","prjct","SKILL.md"),[t,r]=await Promise.all([k(n),k(e)]);return{installed:t,skillInstalled:r,configPath:t?n:void 0}}async function qt(){let n=Qe.configDir;if(!n)return{installed:!1,skillInstalled:!1};let e=await Jt("codex"),t=w.join(n,"skills","prjct","SKILL.md"),r=await k(t),s=!!e;return{installed:s,skillInstalled:r,configPath:s?n:void 0}}function tn(n){let e=z[n];return e.configDir?w.join(e.configDir,e.contextFile):null}function rn(n){let e=z[n];return!e.configDir||!e.settingsFile?null:w.join(e.configDir,e.settingsFile)}function nn(n){return z[n].skillsDir}function sn(n){return z[n].commandsDir}function on(n,e){let t=z[n];return w.join(e,t.commandsDir)}async function an(){let n=await Ze(),e=n.claude.installed,t=n.gemini.installed;return!e&&!t?{provider:"claude",userSelected:!1,detection:n}:e&&!t?{provider:"claude",userSelected:!1,detection:n}:t&&!e?{provider:"gemini",userSelected:!1,detection:n}:{provider:"claude",userSelected:!0,detection:n}}var $t,zt,Br,ve,Ye,We,Gt,Xt,Qe,z,fe=ee(()=>{"use strict";ge();me();Ut();$t=Kr(Hr),zt=2e3,Br={full:{shell:!0,fileRead:!0,fileWrite:!0,fileSearch:!0,structuredQuestions:!0,subagents:!0,webFetch:!0,todoTracking:!0},standard:{shell:!0,fileRead:!0,fileWrite:!0,fileSearch:!0,structuredQuestions:!0,subagents:!1,webFetch:!1,todoTracking:!1},basic:{shell:!0,fileRead:!0,fileWrite:!0,fileSearch:!0,structuredQuestions:!1,subagents:!1,webFetch:!1,todoTracking:!1}};o(qr,"getCapabilities");ve={name:"claude",displayName:"Claude Code",cliCommand:"claude",configDir:w.join(Y.homedir(),".claude"),contextFile:"CLAUDE.md",skillsDir:w.join(Y.homedir(),".claude","skills"),commandsDir:".claude/commands",commandFormat:"md",settingsFile:"settings.json",projectSettingsFile:"settings.local.json",ignoreFile:".claudeignore",websiteUrl:"https://www.anthropic.com/claude",docsUrl:"https://docs.anthropic.com/claude-code",defaultModel:"sonnet",supportedModels:["opus","sonnet","haiku"],minCliVersion:"1.0.0",capabilityTier:"full"},Ye={name:"gemini",displayName:"Gemini CLI",cliCommand:"gemini",configDir:w.join(Y.homedir(),".gemini"),contextFile:"GEMINI.md",skillsDir:w.join(Y.homedir(),".gemini","skills"),commandsDir:".gemini/commands",commandFormat:"toml",settingsFile:"settings.json",projectSettingsFile:"settings.json",ignoreFile:".geminiignore",websiteUrl:"https://geminicli.com",docsUrl:"https://geminicli.com/docs",defaultModel:"2.5-flash",supportedModels:["2.5-pro","2.5-flash","2.0-flash"],minCliVersion:"1.0.0",capabilityTier:"standard"},We={name:"antigravity",displayName:"Google Antigravity",cliCommand:null,configDir:w.join(Y.homedir(),".gemini","antigravity"),contextFile:"ANTIGRAVITY.md",skillsDir:w.join(Y.homedir(),".gemini","antigravity","global_skills"),commandsDir:".agent/skills",commandFormat:"md",settingsFile:"mcp_config.json",projectSettingsFile:null,ignoreFile:".agentignore",websiteUrl:"https://gemini.google.com/app/antigravity",docsUrl:"https://gemini.google.com/app/antigravity",defaultModel:null,supportedModels:[],minCliVersion:null,capabilityTier:"basic"},Gt={name:"cursor",displayName:"Cursor IDE",cliCommand:null,configDir:null,contextFile:"prjct.mdc",skillsDir:null,commandsDir:".cursor/commands",rulesDir:".cursor/rules",commandFormat:"md",settingsFile:null,projectSettingsFile:null,ignoreFile:".cursorignore",isProjectLevel:!0,websiteUrl:"https://cursor.com",docsUrl:"https://cursor.com/docs",defaultModel:null,supportedModels:[],minCliVersion:null,capabilityTier:"basic"},Xt={name:"windsurf",displayName:"Windsurf IDE",cliCommand:null,configDir:null,contextFile:"prjct.md",skillsDir:null,commandsDir:".windsurf/workflows",rulesDir:".windsurf/rules",commandFormat:"md",settingsFile:null,projectSettingsFile:null,ignoreFile:".windsurfignore",isProjectLevel:!0,websiteUrl:"https://windsurf.com",docsUrl:"https://docs.windsurf.com",defaultModel:null,supportedModels:[],minCliVersion:null,capabilityTier:"basic"},Qe={name:"codex",displayName:"OpenAI Codex",cliCommand:"codex",configDir:w.join(Y.homedir(),".codex"),contextFile:"AGENTS.md",skillsDir:w.join(Y.homedir(),".codex","skills"),commandsDir:".agents/skills",commandFormat:"md",settingsFile:null,projectSettingsFile:null,ignoreFile:".codexignore",websiteUrl:"https://openai.com/codex",docsUrl:"https://github.com/openai/codex",defaultModel:null,supportedModels:[],minCliVersion:null,capabilityTier:"basic"},z={claude:ve,gemini:Ye,cursor:Gt,antigravity:We,windsurf:Xt,codex:Qe};o(Jt,"whichCommand");o(Vr,"getCliVersion");o(Ve,"detectProvider");o(Ht,"validateCliVersion");o(Ze,"detectAllProviders");o(Yr,"getActiveProvider");o(Wr,"hasProviderConfig");o(Ae,"getProviderBranding");o(Kt,"detectCursorProject");o(Qr,"needsCursorRouterRegeneration");o(Bt,"detectWindsurfProject");o(Zr,"needsWindsurfRouterRegeneration");o(en,"detectAntigravity");o(qt,"detectCodex");o(tn,"getGlobalContextPath");o(rn,"getGlobalSettingsPath");o(nn,"getSkillsPath");o(sn,"getCommandsDir");o(on,"getProjectCommandsPath");o(an,"selectProvider")});var K=class{static{o(this,"TTLCache")}cache=new Map;ttl;maxSize;constructor(e={}){this.ttl=e.ttl??5e3,this.maxSize=e.maxSize??50}isValid(e){let t=this.cache.get(e);return t?Date.now()-t.timestamp<this.ttl:!1}get(e){let t=this.cache.get(e);return t?this.isValid(e)?t.data:(this.cache.delete(e),null):null}set(e,t){this.cache.set(e,{data:t,timestamp:Date.now()}),this.evictOldEntries()}delete(e){this.cache.delete(e)}clear(){this.cache.clear()}has(e){return this.cache.has(e)}get size(){return this.cache.size}evictOldEntries(){if(this.cache.size<=this.maxSize)return;let t=Array.from(this.cache.entries()).sort((r,s)=>r[1].timestamp-s[1].timestamp).slice(0,this.cache.size-this.maxSize);for(let[r]of t)this.cache.delete(r)}stats(){return{size:this.cache.size,maxSize:this.maxSize,ttl:this.ttl}}prune(){let e=0;for(let t of this.cache.keys())this.isValid(t)||(this.cache.delete(t),e++);return e}};var xe=300*1e3,D=new K({ttl:xe,maxSize:100}),$=new K({ttl:xe,maxSize:10}),ne=new K({ttl:xe,maxSize:5}),se=new K({ttl:xe,maxSize:5});function Je(){D.clear(),$.clear(),ne.clear(),se.clear()}o(Je,"clearLinearCache");function He(){return{issues:D.stats(),assignedIssues:$.stats(),teams:ne.stats(),projects:se.stats()}}o(He,"getLinearCacheStats");X();be();var Or={backlog:"backlog",unstarted:"todo",started:"in_progress",completed:"done",canceled:"cancelled",cancelled:"cancelled"},jr={0:"none",1:"urgent",2:"high",3:"medium",4:"low"},bt={none:0,urgent:1,high:2,medium:3,low:4},Pe=class{static{o(this,"LinearProvider")}name="linear";displayName="Linear";sdk=null;config=null;isConfigured(){return this.sdk!==null&&this.config?.enabled===!0}async initialize(e){this.config=e;let t=e.apiKey||await ie("linear-api-key");if(!t)throw new Error("LINEAR_API_KEY not configured. Run `p. linear setup` to configure.");let{LinearClient:r}=await import("@linear/sdk");this.sdk=new r({apiKey:t});try{await this.sdk.viewer}catch(s){throw this.sdk=null,new Error(`Linear connection failed: ${O(s)}`)}}async fetchAssignedIssues(e){if(!this.sdk)throw new Error("Linear not initialized");let t=await this.sdk.viewer,r={};e?.includeCompleted||(r.state={type:{nin:["completed","canceled"]}}),this.config?.defaultTeamId&&(r.team={id:{eq:this.config.defaultTeamId}});let s=await t.assignedIssues({first:e?.limit||50,filter:Object.keys(r).length>0?r:void 0});return Promise.all(s.nodes.map(i=>this.mapIssue(i)))}async fetchTeamIssues(e,t){if(!this.sdk)throw new Error("Linear not initialized");let s=await(await this.sdk.team(e)).issues({first:t?.limit||50,filter:t?.includeCompleted?void 0:{state:{type:{nin:["completed","canceled"]}}}});return Promise.all(s.nodes.map(i=>this.mapIssue(i)))}async fetchIssue(e){if(!this.sdk)throw new Error("Linear not initialized");try{if(e.includes("-")&&/^[A-Z]+-\d+$/.test(e)){let r=e.match(/^([A-Z]+)-(\d+)$/);if(!r)return null;let[,s,i]=r,u=parseInt(i,10),x=(await this.sdk.teams({first:50})).nodes.find(F=>F.key===s);if(!x)return null;let C=await x.issues({first:1,filter:{number:{eq:u}}});return C.nodes.length>0?this.mapIssue(C.nodes[0]):null}let t=await this.sdk.issue(e);return this.mapIssue(t)}catch{return null}}async createIssue(e){if(!this.sdk)throw new Error("Linear not initialized");let t=e.teamId||this.config?.defaultTeamId;if(!t)throw new Error("Team ID required for creating issues");let s=await(await this.sdk.createIssue({teamId:t,title:e.title,description:e.description,priority:e.priority?bt[e.priority]:void 0,projectId:e.projectId||this.config?.defaultProjectId,assigneeId:e.assigneeId,labelIds:e.labels?await this.resolveLabelIds(t,e.labels):void 0})).issue;if(!s)throw new Error("Failed to create issue");return this.mapIssue(s)}async updateIssue(e,t){if(!this.sdk)throw new Error("Linear not initialized");let r=await this.fetchIssue(e);if(!r)throw new Error(`Issue ${e} not found`);let s={};t.title!==void 0&&(s.title=t.title),t.description!==void 0&&(s.description=t.description),t.priority!==void 0&&(s.priority=bt[t.priority]),t.assigneeId!==void 0&&(s.assigneeId=t.assigneeId),t.stateId!==void 0&&(s.stateId=t.stateId),t.projectId!==void 0&&(s.projectId=t.projectId),t.labels!==void 0&&r.team&&(s.labelIds=await this.resolveLabelIds(r.team.id,t.labels)),await this.sdk.updateIssue(r.id,s);let i=await this.fetchIssue(r.id);if(!i)throw new Error("Failed to fetch updated issue");return i}async markInProgress(e){if(!this.sdk)throw new Error("Linear not initialized");let t=await this.fetchIssue(e);if(!t)throw new Error(`Issue ${e} not found`);let s=await(await this.sdk.issue(t.id)).team;if(!s)throw new Error("Issue has no team");let u=(await s.states()).nodes.find(p=>p.type==="started");u&&await this.sdk.updateIssue(t.id,{stateId:u.id})}async markDone(e){if(!this.sdk)throw new Error("Linear not initialized");let t=await this.fetchIssue(e);if(!t)throw new Error(`Issue ${e} not found`);let s=await(await this.sdk.issue(t.id)).team;if(!s)throw new Error("Issue has no team");let u=(await s.states()).nodes.find(p=>p.type==="completed");u&&await this.sdk.updateIssue(t.id,{stateId:u.id})}async addComment(e,t){if(!this.sdk)throw new Error("Linear not initialized");let r=await this.fetchIssue(e);if(!r)throw new Error(`Issue ${e} not found`);await this.sdk.createComment({issueId:r.id,body:t})}async getTeams(){if(!this.sdk)throw new Error("Linear not initialized");return(await this.sdk.teams({first:50})).nodes.map(t=>({id:t.id,name:t.name,key:t.key}))}async getProjects(){if(!this.sdk)throw new Error("Linear not initialized");return(await this.sdk.projects({first:50})).nodes.map(t=>({id:t.id,name:t.name}))}async mapIssue(e){let t=await e.state,r=await e.assignee,s=await e.team,i=await e.project,u=await e.labels();return{id:e.id,externalId:e.identifier,provider:"linear",title:e.title,description:e.description||void 0,status:Or[t?.type||"backlog"]||"backlog",priority:jr[e.priority]||"none",type:this.inferType(e.title,u.nodes.map(p=>p.name)),assignee:r?{id:r.id,name:r.name,email:r.email}:void 0,labels:u.nodes.map(p=>p.name),team:s?{id:s.id,name:s.name,key:s.key}:void 0,project:i?{id:i.id,name:i.name}:void 0,url:e.url,createdAt:e.createdAt.toISOString(),updatedAt:e.updatedAt.toISOString(),raw:e}}inferType(e,t){let r=e.toLowerCase(),s=t.map(i=>i.toLowerCase());return s.includes("bug")||r.includes("fix")||r.includes("bug")?"bug":s.includes("feature")||r.includes("add")||r.includes("implement")?"feature":s.includes("improvement")||r.includes("improve")||r.includes("enhance")?"improvement":s.includes("chore")||r.includes("chore")||r.includes("deps")?"chore":"task"}async resolveLabelIds(e,t){return this.sdk?(await(await this.sdk.team(e)).labels()).nodes.filter(i=>t.includes(i.name)).map(i=>i.id):[]}},j=new Pe;var Ie=class{static{o(this,"LinearService")}initialized=!1;userId=null;isReady(){return this.initialized&&j.isConfigured()}async initialize(e){this.initialized||(await j.initialize(e),this.initialized=!0)}async initializeFromApiKey(e,t){let r={enabled:!0,provider:"linear",apiKey:e,defaultTeamId:t,syncOn:{task:!0,done:!0,ship:!0},enrichment:{enabled:!0,updateProvider:!0}};await this.initialize(r)}async fetchAssignedIssues(e){this.ensureInitialized();let t=`assigned:${this.userId||"me"}`,r=$.get(t);if(r)return r;let s=await j.fetchAssignedIssues(e);$.set(t,s);for(let i of s)D.set(`issue:${i.id}`,i),D.set(`issue:${i.externalId}`,i);return s}async fetchTeamIssues(e,t){this.ensureInitialized();let r=`team:${e}`,s=$.get(r);if(s)return s;let i=await j.fetchTeamIssues(e,t);$.set(r,i);for(let u of i)D.set(`issue:${u.id}`,u),D.set(`issue:${u.externalId}`,u);return i}async fetchIssue(e){this.ensureInitialized();let t=`issue:${e}`,r=D.get(t);if(r)return r;let s=await j.fetchIssue(e);return s&&(D.set(`issue:${s.id}`,s),D.set(`issue:${s.externalId}`,s)),s}async createIssue(e){this.ensureInitialized();let t=await j.createIssue(e);return D.set(`issue:${t.id}`,t),D.set(`issue:${t.externalId}`,t),$.clear(),t}async updateIssue(e,t){this.ensureInitialized();let r=await j.updateIssue(e,t);return D.set(`issue:${r.id}`,r),D.set(`issue:${r.externalId}`,r),r}async markInProgress(e){this.ensureInitialized(),await j.markInProgress(e),D.delete(`issue:${e}`),$.clear()}async markDone(e){this.ensureInitialized(),await j.markDone(e),D.delete(`issue:${e}`),$.clear()}async addComment(e,t){this.ensureInitialized(),await j.addComment(e,t)}async getTeams(){this.ensureInitialized();let e=ne.get("teams");if(e)return e;let t=await j.getTeams();return ne.set("teams",t),t}async getProjects(){this.ensureInitialized();let e=se.get("projects");if(e)return e;let t=await j.getProjects();return se.set("projects",t),t}clearCache(){Je()}getCacheStats(){return He()}ensureInitialized(){if(!this.initialized)throw new Error("Linear service not initialized. Call linearService.initialize() first or run `p. linear setup`.")}},T=new Ie;import{z as g}from"zod";var Pt=g.enum(["linear","jira","github","monday","asana","none"]),Mr=g.enum(["backlog","todo","in_progress","in_review","done","cancelled"]),Fr=g.enum(["none","urgent","high","medium","low"]),Ur=g.enum(["feature","bug","improvement","task","chore","epic"]),$r=g.object({id:g.string(),identifier:g.string(),title:g.string(),description:g.string().optional(),status:Mr,priority:Fr,type:Ur.optional(),assignee:g.object({id:g.string(),name:g.string(),email:g.string().optional()}).optional(),labels:g.array(g.string()).default([]),team:g.object({id:g.string(),name:g.string(),key:g.string().optional()}).optional(),project:g.object({id:g.string(),name:g.string()}).optional(),url:g.string(),createdAt:g.string(),updatedAt:g.string(),fetchedAt:g.string()}),gi=g.object({provider:Pt,lastSync:g.string(),staleAfter:g.number().default(18e5),issues:g.record(g.string(),$r)}),fi=g.object({provider:Pt,fetched:g.number(),updated:g.number(),errors:g.array(g.object({issueId:g.string(),error:g.string()})),timestamp:g.string()});function It(n){return{provider:n,lastSync:"",staleAfter:18e5,issues:{}}}o(It,"createEmptyIssues");import rt from"node:fs";import Yt from"node:path";import cn from"node:crypto";import H from"node:fs/promises";import et from"node:os";import d from"node:path";import{globSync as ln}from"glob";import{formatDistanceToNowStrict as Ei}from"date-fns";function kt(n){return{year:n.getFullYear().toString(),month:(n.getMonth()+1).toString().padStart(2,"0"),day:n.getDate().toString().padStart(2,"0")}}o(kt,"getYearMonthDay");function I(){return new Date().toISOString()}o(I,"getTimestamp");function wt(n){let e=new Date;return e.setDate(e.getDate()-n),e}o(wt,"getDaysAgo");me();var tt=class{static{o(this,"PathManager")}globalBaseDir;globalProjectsDir;globalConfigDir;constructor(){let e=process.env.PRJCT_CLI_HOME?.trim();this.globalBaseDir=e?d.resolve(e):d.join(et.homedir(),".prjct-cli"),this.globalProjectsDir=d.join(this.globalBaseDir,"projects"),this.globalConfigDir=d.join(this.globalBaseDir,"config")}setGlobalBaseDir(e){this.globalBaseDir=d.resolve(e),this.globalProjectsDir=d.join(this.globalBaseDir,"projects"),this.globalConfigDir=d.join(this.globalBaseDir,"config")}generateProjectId(e){return cn.randomUUID()}getGlobalBasePath(){return this.globalBaseDir}getGlobalProjectPath(e){return d.join(this.globalProjectsDir,e)}getLocalConfigPath(e){return d.join(e,".prjct","prjct.config.json")}getGlobalProjectConfigPath(e){return d.join(this.getGlobalProjectPath(e),"project.json")}getLegacyPrjctPath(e){return d.join(e,".prjct")}async hasLegacyStructure(e){let t=this.getLegacyPrjctPath(e);return await Be(t)}async hasConfig(e){let t=this.getLocalConfigPath(e);return await k(t)}async ensureGlobalStructure(){await V(this.globalBaseDir),await V(this.globalProjectsDir),await V(this.globalConfigDir)}async ensureProjectStructure(e){await this.ensureGlobalStructure();let t=this.getGlobalProjectPath(e),r=["core","progress","planning","analysis","memory","agents"];for(let s of r)await V(d.join(t,s));return await V(d.join(t,"planning","tasks")),await V(d.join(t,"sessions")),t}getSessionPath(e,t=new Date){let{year:r,month:s,day:i}=kt(t);return d.join(this.getGlobalProjectPath(e),"sessions",r,s,i)}getCurrentSessionPath(e){return this.getSessionPath(e,new Date)}async ensureSessionPath(e,t=new Date){let r=this.getSessionPath(e,t);return await V(r),r}async listSessions(e,t=null,r=null){let s=d.join(this.getGlobalProjectPath(e),"sessions"),i=[];try{let u=await H.readdir(s,{withFileTypes:!0});for(let p of u){if(!p.isDirectory()||t&&p.name!==t.toString())continue;let x=d.join(s,p.name),C=await H.readdir(x,{withFileTypes:!0});for(let F of C){if(!F.isDirectory()||r&&F.name!==r.toString().padStart(2,"0"))continue;let Se=d.join(x,F.name),Ge=await H.readdir(Se,{withFileTypes:!0});for(let Ee of Ge)Ee.isDirectory()&&i.push({year:p.name,month:F.name,day:Ee.name,path:d.join(Se,Ee.name),date:new Date(`${p.name}-${F.name}-${Ee.name}`)})}}return i.sort((p,x)=>x.date.getTime()-p.date.getTime()),i}catch{return[]}}async getSessionsInRange(e,t,r=new Date){return(await this.listSessions(e)).filter(i=>i.date>=t&&i.date<=r)}getFilePath(e,t,r){return d.join(this.getGlobalProjectPath(e),t,r)}async listProjects(){try{return await this.ensureGlobalStructure(),(await H.readdir(this.globalProjectsDir,{withFileTypes:!0})).filter(t=>t.isDirectory()).map(t=>t.name)}catch{return[]}}async projectExists(e){let t=this.getGlobalProjectPath(e);return await Be(t)}getDisplayPath(e){let t=et.homedir();return e.startsWith(t)?e.replace(t,"~"):e}getAuthConfigPath(){return d.join(this.globalConfigDir,"auth.json")}getSyncPendingPath(e){return d.join(this.getGlobalProjectPath(e),"sync","pending.json")}getLastSyncPath(e){return d.join(this.getGlobalProjectPath(e),"sync","last-sync.json")}getRunningStatusPath(){return d.join(this.globalBaseDir,".running")}getDocsPath(){return d.join(this.globalBaseDir,"docs")}async getAgentDir(){return(await(fe(),Xe(Ce)).getActiveProvider()).configDir}async getAgentSettingsPath(){let e=await(fe(),Xe(Ce)).getActiveProvider();return(fe(),Xe(Ce)).getGlobalSettingsPath(e.name)}getClaudeDir(){return d.join(et.homedir(),".claude")}getClaudeSettingsPath(){return d.join(this.getClaudeDir(),"settings.json")}getAgentsPath(e){return e?d.join(this.getGlobalProjectPath(e),"agents"):d.join(this.globalBaseDir,"agents")}getStoragePath(e,t){return d.join(this.getGlobalProjectPath(e),"storage",t)}getContextPath(e){return d.join(this.getGlobalProjectPath(e),"context")}async detectMonorepo(e){let t={isMonorepo:!1,type:null,rootPath:e,packages:[]},r=[{file:"pnpm-workspace.yaml",type:"pnpm"},{file:"lerna.json",type:"lerna"},{file:"nx.json",type:"nx"},{file:"rush.json",type:"rush"},{file:"turbo.json",type:"turborepo"}];for(let s of r){let i=d.join(e,s.file);if(await k(i)){t.isMonorepo=!0,t.type=s.type;break}}if(!t.isMonorepo){let s=d.join(e,"package.json");if(await k(s))try{let i=await H.readFile(s,"utf-8");JSON.parse(i).workspaces&&(t.isMonorepo=!0,t.type="npm")}catch{}}return t.isMonorepo&&(t.packages=await this.discoverMonorepoPackages(e,t.type)),t}async discoverMonorepoPackages(e,t){let r=[],s=[];try{if(t==="pnpm"){let u=(await H.readFile(d.join(e,"pnpm-workspace.yaml"),"utf-8")).match(/packages:\s*\n((?:\s*-\s*.+\n?)+)/);u&&(s=u[1].split(`
9
- `).map(p=>p.replace(/^\s*-\s*['"]?|['"]?\s*$/g,"")).filter(Boolean))}else if(t==="npm"||t==="lerna"){let i=d.join(e,"package.json"),u=await H.readFile(i,"utf-8"),p=JSON.parse(u);if(Array.isArray(p.workspaces)?s=p.workspaces:p.workspaces?.packages&&(s=p.workspaces.packages),t==="lerna"){let x=d.join(e,"lerna.json");if(await k(x)){let C=await H.readFile(x,"utf-8"),F=JSON.parse(C);F.packages&&(s=F.packages)}}}else if(t==="nx")s=["apps/*","libs/*","packages/*"];else if(t==="turborepo"){let i=d.join(e,"package.json"),u=await H.readFile(i,"utf-8"),p=JSON.parse(u);Array.isArray(p.workspaces)&&(s=p.workspaces)}s.length===0&&(s=["packages/*","apps/*","libs/*"]);for(let i of s){if(i.startsWith("!"))continue;let u=ln(i,{cwd:e,absolute:!1});for(let p of u){let x=d.join(e,p),C=d.join(x,"package.json");if(await k(C))try{let F=await H.readFile(C,"utf-8"),Se=JSON.parse(F),Ge=d.join(x,"PRJCT.md");r.push({name:Se.name||d.basename(p),path:x,relativePath:p,hasPrjctMd:await k(Ge)})}catch{}}}}catch{}return r}async findContainingPackage(e,t){if(!t.isMonorepo)return null;let r=d.resolve(e);for(let s of t.packages){let i=d.resolve(s.path);if(r.startsWith(i))return s}return null}async findMonorepoRoot(e){let t=d.resolve(e),r=d.parse(t).root;for(;t!==r;){if((await this.detectMonorepo(t)).isMonorepo)return t;t=d.dirname(t)}return null}},un=new tt,W=un;function pn(){return typeof globalThis<"u"&&"Bun"in globalThis?"bun":"node"}o(pn,"detectRuntime");function Vt(){return pn()==="bun"}o(Vt,"isBun");function dn(n){if(Vt()){let{Database:s}=St("bun:sqlite");return new s(n,{create:!0})}let e=St("better-sqlite3"),t=new e(n),r=t.exec.bind(t);return t.run=s=>r(s),t}o(dn,"openDatabase");var mn=[{version:1,name:"initial-schema",up:o(n=>{n.run(`
10
- -- =======================================================================
11
- -- Document storage (backward-compatible with JSON file pattern)
12
- -- =======================================================================
13
- -- Each row replaces one JSON file (state.json, queue.json, etc.)
14
- -- StorageManager reads/writes entire documents via key lookup.
15
- CREATE TABLE kv_store (
16
- key TEXT PRIMARY KEY,
17
- data TEXT NOT NULL,
18
- updated_at TEXT NOT NULL
19
- );
20
-
21
- -- =======================================================================
22
- -- Normalized: Tasks
23
- -- =======================================================================
24
- CREATE TABLE tasks (
25
- id TEXT PRIMARY KEY,
26
- description TEXT NOT NULL,
27
- type TEXT,
28
- status TEXT NOT NULL,
29
- parent_description TEXT,
30
- branch TEXT,
31
- linear_id TEXT,
32
- linear_uuid TEXT,
33
- session_id TEXT,
34
- feature_id TEXT,
35
- started_at TEXT NOT NULL,
36
- completed_at TEXT,
37
- shipped_at TEXT,
38
- paused_at TEXT,
39
- pause_reason TEXT,
40
- pr_url TEXT,
41
- expected_value TEXT,
42
- data TEXT
43
- );
44
-
45
- CREATE INDEX idx_tasks_status ON tasks(status);
46
- CREATE INDEX idx_tasks_type ON tasks(type);
47
- CREATE INDEX idx_tasks_branch ON tasks(branch);
48
- CREATE INDEX idx_tasks_linear_id ON tasks(linear_id);
49
-
50
- -- =======================================================================
51
- -- Normalized: Subtasks
52
- -- =======================================================================
53
- CREATE TABLE subtasks (
54
- id TEXT PRIMARY KEY,
55
- task_id TEXT NOT NULL,
56
- description TEXT NOT NULL,
57
- status TEXT NOT NULL,
58
- domain TEXT,
59
- agent TEXT,
60
- sort_order INTEGER NOT NULL,
61
- depends_on TEXT,
62
- started_at TEXT,
63
- completed_at TEXT,
64
- output TEXT,
65
- summary TEXT,
66
- FOREIGN KEY (task_id) REFERENCES tasks(id)
67
- );
68
-
69
- CREATE INDEX idx_subtasks_task_id ON subtasks(task_id);
70
- CREATE INDEX idx_subtasks_status ON subtasks(status);
71
-
72
- -- =======================================================================
73
- -- Normalized: Queue Tasks
74
- -- =======================================================================
75
- CREATE TABLE queue_tasks (
76
- id TEXT PRIMARY KEY,
77
- description TEXT NOT NULL,
78
- type TEXT,
79
- priority TEXT,
80
- section TEXT,
81
- created_at TEXT NOT NULL,
82
- completed INTEGER DEFAULT 0,
83
- completed_at TEXT,
84
- feature_id TEXT,
85
- feature_name TEXT
86
- );
87
-
88
- CREATE INDEX idx_queue_tasks_section ON queue_tasks(section);
89
- CREATE INDEX idx_queue_tasks_priority ON queue_tasks(priority);
90
- CREATE INDEX idx_queue_tasks_completed ON queue_tasks(completed);
91
-
92
- -- =======================================================================
93
- -- Normalized: Ideas
94
- -- =======================================================================
95
- CREATE TABLE ideas (
96
- id TEXT PRIMARY KEY,
97
- text TEXT NOT NULL,
98
- status TEXT NOT NULL DEFAULT 'pending',
99
- priority TEXT NOT NULL DEFAULT 'medium',
100
- tags TEXT,
101
- added_at TEXT NOT NULL,
102
- converted_to TEXT,
103
- details TEXT,
104
- data TEXT
105
- );
106
-
107
- CREATE INDEX idx_ideas_status ON ideas(status);
108
- CREATE INDEX idx_ideas_priority ON ideas(priority);
109
-
110
- -- =======================================================================
111
- -- Normalized: Shipped Features
112
- -- =======================================================================
113
- CREATE TABLE shipped_features (
114
- id TEXT PRIMARY KEY,
115
- name TEXT NOT NULL,
116
- shipped_at TEXT NOT NULL,
117
- version TEXT NOT NULL,
118
- description TEXT,
119
- type TEXT,
120
- duration TEXT,
121
- data TEXT
122
- );
123
-
124
- CREATE INDEX idx_shipped_version ON shipped_features(version);
125
- CREATE INDEX idx_shipped_at ON shipped_features(shipped_at);
126
-
127
- -- =======================================================================
128
- -- Events (replaces events.jsonl)
129
- -- =======================================================================
130
- CREATE TABLE events (
131
- id INTEGER PRIMARY KEY AUTOINCREMENT,
132
- type TEXT NOT NULL,
133
- task_id TEXT,
134
- data TEXT,
135
- timestamp TEXT NOT NULL
136
- );
137
-
138
- CREATE INDEX idx_events_type ON events(type);
139
- CREATE INDEX idx_events_task_id ON events(task_id);
140
- CREATE INDEX idx_events_timestamp ON events(timestamp);
141
-
142
- -- =======================================================================
143
- -- Analysis (draft + sealed)
144
- -- =======================================================================
145
- CREATE TABLE analysis (
146
- id TEXT PRIMARY KEY,
147
- status TEXT NOT NULL,
148
- commit_hash TEXT,
149
- signature TEXT,
150
- sealed_at TEXT,
151
- analyzed_at TEXT,
152
- data TEXT NOT NULL
153
- );
154
-
155
- -- =======================================================================
156
- -- Index: File scores and checksums
157
- -- =======================================================================
158
- CREATE TABLE index_files (
159
- path TEXT PRIMARY KEY,
160
- score REAL,
161
- size INTEGER,
162
- mtime TEXT,
163
- language TEXT,
164
- categories TEXT,
165
- domain TEXT
166
- );
167
-
168
- CREATE INDEX idx_index_files_domain ON index_files(domain);
169
- CREATE INDEX idx_index_files_score ON index_files(score);
170
-
171
- CREATE TABLE index_checksums (
172
- path TEXT PRIMARY KEY,
173
- checksum TEXT NOT NULL,
174
- size INTEGER,
175
- mtime TEXT
176
- );
177
-
178
- -- =======================================================================
179
- -- Index: Metadata (project-index, domains, categories-cache)
180
- -- =======================================================================
181
- CREATE TABLE index_meta (
182
- key TEXT PRIMARY KEY,
183
- data TEXT NOT NULL,
184
- updated_at TEXT NOT NULL
185
- );
186
-
187
- -- =======================================================================
188
- -- Memory (key-value with domain tagging)
189
- -- =======================================================================
190
- CREATE TABLE memory (
191
- key TEXT PRIMARY KEY,
192
- domain TEXT,
193
- value TEXT,
194
- confidence REAL DEFAULT 1.0,
195
- updated_at TEXT NOT NULL
196
- );
197
-
198
- CREATE INDEX idx_memory_domain ON memory(domain);
199
-
200
- -- =======================================================================
201
- -- Metrics: Daily stats for trend analysis
202
- -- =======================================================================
203
- CREATE TABLE metrics_daily (
204
- date TEXT PRIMARY KEY,
205
- tokens_saved INTEGER NOT NULL DEFAULT 0,
206
- syncs INTEGER NOT NULL DEFAULT 0,
207
- avg_compression_rate REAL NOT NULL DEFAULT 0,
208
- total_duration INTEGER NOT NULL DEFAULT 0
209
- );
210
-
211
- -- =======================================================================
212
- -- Velocity: Sprint data
213
- -- =======================================================================
214
- CREATE TABLE velocity_sprints (
215
- sprint_number INTEGER PRIMARY KEY,
216
- points_completed REAL NOT NULL DEFAULT 0,
217
- tasks_completed INTEGER NOT NULL DEFAULT 0,
218
- estimation_accuracy REAL NOT NULL DEFAULT 0,
219
- avg_variance REAL NOT NULL DEFAULT 0,
220
- started_at TEXT,
221
- ended_at TEXT
222
- );
223
- `)},"up")},{version:2,name:"archives-table",up:o(n=>{n.run(`
224
- -- =======================================================================
225
- -- Archives: Stale data moved out of active storage (PRJ-267)
226
- -- =======================================================================
227
- CREATE TABLE archives (
228
- id TEXT PRIMARY KEY,
229
- entity_type TEXT NOT NULL,
230
- entity_id TEXT NOT NULL,
231
- entity_data TEXT NOT NULL,
232
- summary TEXT,
233
- archived_at TEXT NOT NULL,
234
- reason TEXT NOT NULL
235
- );
236
-
237
- CREATE INDEX idx_archives_entity_type ON archives(entity_type);
238
- CREATE INDEX idx_archives_archived_at ON archives(archived_at);
239
- CREATE INDEX idx_archives_entity_id ON archives(entity_id);
240
- `)},"up")},{version:3,name:"workflow-rules-table",up:o(n=>{n.run(`
241
- -- =======================================================================
242
- -- Workflow Rules: hooks, gates, and custom steps (Phase 2)
243
- -- =======================================================================
244
- CREATE TABLE workflow_rules (
245
- id INTEGER PRIMARY KEY AUTOINCREMENT,
246
- type TEXT NOT NULL,
247
- command TEXT NOT NULL,
248
- position TEXT NOT NULL,
249
- action TEXT NOT NULL,
250
- description TEXT,
251
- enabled INTEGER NOT NULL DEFAULT 1,
252
- timeout_ms INTEGER NOT NULL DEFAULT 60000,
253
- created_at TEXT NOT NULL,
254
- sort_order INTEGER NOT NULL DEFAULT 0
255
- );
256
-
257
- CREATE INDEX idx_workflow_rules_command ON workflow_rules(command);
258
- `)},"up")},{version:4,name:"custom-workflows-table",up:o(n=>{n.run(`
259
- -- =======================================================================
260
- -- Custom Workflows: User-defined workflows with agentic auto-config
261
- -- =======================================================================
262
- CREATE TABLE custom_workflows (
263
- id INTEGER PRIMARY KEY AUTOINCREMENT,
264
- name TEXT UNIQUE NOT NULL,
265
- description TEXT,
266
- created_at TEXT NOT NULL,
267
- updated_at TEXT NOT NULL,
268
- is_builtin INTEGER NOT NULL DEFAULT 0,
269
- enabled INTEGER NOT NULL DEFAULT 1,
270
- metadata TEXT
271
- );
272
-
273
- CREATE INDEX idx_custom_workflows_name ON custom_workflows(name);
274
- CREATE INDEX idx_custom_workflows_enabled ON custom_workflows(enabled);
275
-
276
- -- Seed built-in workflows (task, done, ship, sync)
277
- INSERT INTO custom_workflows (name, description, is_builtin, enabled, created_at, updated_at)
278
- VALUES
279
- ('task', 'Start working on a task', 1, 1, datetime('now'), datetime('now')),
280
- ('done', 'Complete current task/subtask', 1, 1, datetime('now'), datetime('now')),
281
- ('ship', 'Ship feature with version bump and PR', 1, 1, datetime('now'), datetime('now')),
282
- ('sync', 'Analyze project and regenerate context', 1, 1, datetime('now'), datetime('now'));
283
- `)},"up")},{version:5,name:"llm-analysis-table",up:o(n=>{n.run(`
284
- -- =======================================================================
285
- -- LLM Analysis: Structured findings from hybrid sync pipeline
286
- -- Pipeline: CLI (collect) \u2192 LLM (analyze) \u2192 CLI (store)
287
- -- =======================================================================
288
- CREATE TABLE llm_analysis (
289
- id INTEGER PRIMARY KEY AUTOINCREMENT,
290
- commit_hash TEXT,
291
- status TEXT NOT NULL DEFAULT 'active',
292
- analysis TEXT NOT NULL,
293
- analyzed_at TEXT NOT NULL,
294
- superseded_at TEXT
295
- );
296
-
297
- CREATE INDEX idx_llm_analysis_status ON llm_analysis(status);
298
- CREATE INDEX idx_llm_analysis_commit ON llm_analysis(commit_hash);
299
- `)},"up")},{version:6,name:"context-feedback-table",up:o(n=>{n.run(`
300
- -- =======================================================================
301
- -- Context Feedback: RL loop for file suggestion improvement
302
- -- Records suggested vs actual files per task for scoring boosts
303
- -- =======================================================================
304
- CREATE TABLE context_feedback (
305
- id INTEGER PRIMARY KEY AUTOINCREMENT,
306
- task_id TEXT NOT NULL,
307
- keywords TEXT NOT NULL,
308
- suggested_files TEXT NOT NULL,
309
- actual_files TEXT,
310
- precision REAL,
311
- recall REAL,
312
- created_at TEXT NOT NULL,
313
- completed_at TEXT
314
- );
315
-
316
- CREATE INDEX idx_cf_task ON context_feedback(task_id);
317
- `)},"up")},{version:7,name:"sessions-table",up:o(n=>{n.run(`
318
- -- =======================================================================
319
- -- Sessions: Task lifecycle tracking (replaces current.json + archive/)
320
- -- =======================================================================
321
- CREATE TABLE sessions (
322
- id TEXT PRIMARY KEY,
323
- project_id TEXT NOT NULL,
324
- task TEXT NOT NULL,
325
- status TEXT NOT NULL,
326
- started_at TEXT NOT NULL,
327
- paused_at TEXT,
328
- completed_at TEXT,
329
- duration INTEGER NOT NULL DEFAULT 0,
330
- metrics TEXT NOT NULL DEFAULT '{}',
331
- timeline TEXT NOT NULL DEFAULT '[]'
332
- );
333
-
334
- CREATE INDEX idx_sessions_project ON sessions(project_id);
335
- CREATE INDEX idx_sessions_status ON sessions(status);
336
- CREATE INDEX idx_sessions_completed ON sessions(completed_at);
337
- `)},"up")}],nt=class{static{o(this,"PrjctDatabase")}connections=new Map;getDbPath(e){return Yt.join(W.getGlobalProjectPath(e),"prjct.db")}getDb(e){let t=this.connections.get(e);if(t)return t;let r=this.getDbPath(e),s=Yt.dirname(r);rt.existsSync(s)||rt.mkdirSync(s,{recursive:!0});let i=dn(r);return i.run("PRAGMA journal_mode = WAL"),i.run("PRAGMA synchronous = NORMAL"),i.run("PRAGMA cache_size = -2000"),i.run("PRAGMA temp_store = MEMORY"),i.run("PRAGMA mmap_size = 268435456"),this.runMigrations(i),this.connections.set(e,i),i}close(e){if(e){let t=this.connections.get(e);t&&(t.close(),this.connections.delete(e))}else this.connections.forEach(t=>{t.close()}),this.connections.clear()}exists(e){return rt.existsSync(this.getDbPath(e))}getDoc(e,t){let s=this.getDb(e).prepare("SELECT data FROM kv_store WHERE key = ?").get(t);return s?JSON.parse(s.data):null}setDoc(e,t,r){let s=this.getDb(e),i=JSON.stringify(r),u=new Date().toISOString();s.prepare("INSERT OR REPLACE INTO kv_store (key, data, updated_at) VALUES (?, ?, ?)").run(t,i,u)}deleteDoc(e,t){this.getDb(e).prepare("DELETE FROM kv_store WHERE key = ?").run(t)}hasDoc(e,t){return this.getDb(e).prepare("SELECT 1 FROM kv_store WHERE key = ?").get(t)!==null}appendEvent(e,t,r,s){let i=this.getDb(e),u=new Date().toISOString();i.prepare("INSERT INTO events (type, task_id, data, timestamp) VALUES (?, ?, ?, ?)").run(t,s??null,JSON.stringify(r),u)}getEvents(e,t,r=100){let s=this.getDb(e);return t?s.prepare("SELECT * FROM events WHERE type = ? ORDER BY id DESC LIMIT ?").all(t,r):s.prepare("SELECT * FROM events ORDER BY id DESC LIMIT ?").all(r)}query(e,t,...r){return this.getDb(e).prepare(t).all(...r)}run(e,t,...r){this.getDb(e).prepare(t).run(...r)}get(e,t,...r){return this.getDb(e).prepare(t).get(...r)??null}transaction(e,t){let r=this.getDb(e);return r.transaction(t)(r)}runMigrations(e){e.run(`
338
- CREATE TABLE IF NOT EXISTS _migrations (
339
- version INTEGER PRIMARY KEY,
340
- name TEXT NOT NULL,
341
- applied_at TEXT NOT NULL
342
- )
343
- `);let t=new Set(e.prepare("SELECT version FROM _migrations").all().map(r=>r.version));for(let r of mn)t.has(r.version)||e.transaction(()=>{r.up(e),e.prepare("INSERT INTO _migrations (version, name, applied_at) VALUES (?, ?, ?)").run(r.version,r.name,new Date().toISOString())})()}getMigrations(e){return this.getDb(e).prepare("SELECT * FROM _migrations ORDER BY version").all()}getSchemaVersion(e){return this.getDb(e).prepare("SELECT MAX(version) as version FROM _migrations").get()?.version??0}},P=new nt;X();ge();import{z as f}from"zod";var gn=f.enum(["draft","verified","sealed"]),fn=f.object({name:f.string(),description:f.string(),location:f.string().optional(),severity:f.enum(["low","medium","high"]).optional(),language:f.string().optional(),framework:f.string().optional(),source:f.enum(["baseline","repo","context7","feedback"]).optional(),confidence:f.number().min(0).max(1).optional()}),hn=f.object({issue:f.string(),file:f.string(),suggestion:f.string(),severity:f.enum(["low","medium","high"]).optional(),language:f.string().optional(),framework:f.string().optional(),source:f.enum(["baseline","repo","context7","feedback"]).optional(),confidence:f.number().min(0).max(1).optional()}),fo=f.object({projectId:f.string(),languages:f.array(f.string()),frameworks:f.array(f.string()),packageManager:f.string().optional(),sourceDir:f.string().optional(),testDir:f.string().optional(),configFiles:f.array(f.string()),fileCount:f.number(),patterns:f.array(fn),antiPatterns:f.array(hn),analyzedAt:f.string(),modelMetadata:oe.optional(),status:gn.default("draft"),commitHash:f.string().optional(),signature:f.string().optional(),sealedAt:f.string().optional(),verifiedAt:f.string().optional()});var ho={languages:[],frameworks:[],configFiles:[],fileCount:0,patterns:[],antiPatterns:[],analyzedAt:new Date().toISOString(),status:"draft"};import{z as b}from"zod";var Re=b.enum(["frontend","backend","database","devops","testing","docs","uxui","general"]),he=b.object({primaryDomain:Re,secondaryDomains:b.array(Re),confidence:b.number().min(0).max(1),filePatterns:b.array(b.string()),relevantAgents:b.array(b.string())}),yn=b.object({classification:he,classifiedAt:b.string(),source:b.enum(["cache","history","llm","heuristic"]),descriptionHash:b.string(),projectId:b.string()}),To=b.object({entries:b.record(b.string(),yn),confirmedPatterns:b.array(b.object({descriptionHash:b.string(),classification:he,confirmedAt:b.string(),taskDescription:b.string()}))});import{z as m}from"zod";var Sn=m.enum(["low","medium","high"]),En=m.enum(["pending","converted","completed","archived","dormant"]),Wt=m.enum(["high","medium","low"]),Tn=m.object({impact:Wt,effort:Wt}),xn=m.object({frontend:m.string().optional(),backend:m.string().optional(),payments:m.string().optional(),ai:m.string().optional(),deploy:m.string().optional(),other:m.array(m.string()).optional()}),bn=m.object({name:m.string(),description:m.string()}),Pn=m.object({name:m.string(),description:m.string().optional()}),In=m.object({id:m.string(),text:m.string(),details:m.string().optional(),priority:Sn,status:En,tags:m.array(m.string()),addedAt:m.string(),completedAt:m.string().optional(),convertedTo:m.string().optional(),source:m.string().optional(),sourceFiles:m.array(m.string()).optional(),painPoints:m.array(m.string()).optional(),solutions:m.array(m.string()).optional(),filesAffected:m.array(m.string()).optional(),impactEffort:Tn.optional(),implementationNotes:m.string().optional(),stack:xn.optional(),modules:m.array(bn).optional(),roles:m.array(Pn).optional(),risks:m.array(m.string()).optional(),risksCount:m.number().optional()}),Po=m.object({ideas:m.array(In),lastUpdated:m.string()});var Io={priority:"medium",status:"pending",tags:[],addedAt:new Date().toISOString()};import{z as U}from"zod";var kn=U.object({agentName:U.string(),reasoning:U.string(),confidence:U.number().min(0).max(1)}),wn=U.object({subtasks:U.array(U.object({description:U.string(),domain:Re,agent:U.string(),dependsOn:U.array(U.number())})),effort:U.enum(["low","medium","high"])}),Co={classification:{schema:he,example:JSON.stringify({primaryDomain:"backend",secondaryDomains:["database"],confidence:.9,filePatterns:["src/api/**"],relevantAgents:["backend.md"]},null,2)},agentAssignment:{schema:kn,example:JSON.stringify({agentName:"backend.md",reasoning:"Task involves API endpoint creation",confidence:.85},null,2)},subtaskBreakdown:{schema:wn,example:JSON.stringify({subtasks:[{description:"Add schema validation",domain:"backend",agent:"backend.md",dependsOn:[]},{description:"Add unit tests",domain:"testing",agent:"testing.md",dependsOn:[0]}],effort:"medium"},null,2)}};ge();import{z as c}from"zod";var Qt=c.number().min(1).max(5),vn=c.enum(["exceeded","met","partial","failed"]),An=c.enum(["definitely","probably","maybe","no"]),Zt=c.enum(["scope_creep","underestimated_complexity","technical_debt","external_blockers","learning_curve","requirements_changed","optimistic_estimate","team_changes","other"]),Cn=c.object({estimated:c.object({hours:c.number(),confidence:c.enum(["low","medium","high"]).optional(),source:c.enum(["prd","manual","historical"]).optional()}),actual:c.object({hours:c.number(),commits:c.number().optional(),linesAdded:c.number().optional(),linesRemoved:c.number().optional(),sessions:c.number().optional()}),variance:c.object({hours:c.number(),percentage:c.number(),reason:Zt.optional(),explanation:c.string().optional()})}),Rn=c.object({name:c.string(),baseline:c.number().nullable(),target:c.number(),actual:c.number(),unit:c.string(),achieved:c.boolean(),percentOfTarget:c.number()}),Dn=c.object({criteria:c.string(),met:c.boolean(),notes:c.string().optional()}),_n=c.object({metrics:c.array(Rn),acceptanceCriteria:c.array(Dn),overallSuccess:vn,successScore:c.number().min(0).max(100)}),Ln=c.object({category:c.enum(["estimation","technical","process","communication","tooling","architecture","testing","other"]),insight:c.string(),actionable:c.boolean(),action:c.string().optional()}),Nn=c.object({whatWorked:c.array(c.string()),whatDidnt:c.array(c.string()),surprises:c.array(c.string()),recommendations:c.array(Ln)}),On=c.object({valueDelivered:c.number().min(1).max(10),userImpact:c.enum(["none","low","medium","high","critical"]),businessImpact:c.enum(["none","low","medium","high","critical"]),roiScore:c.number(),worthIt:An,worthItReason:c.string().optional(),alternativeConsidered:c.string().optional(),betterAlternativeExists:c.boolean().optional()}),er=c.object({id:c.string(),taskId:c.string(),description:c.string(),estimatedMinutes:c.number().optional(),actualMinutes:c.number(),completedAsPlanned:c.boolean(),qualityScore:Qt,blockers:c.array(c.string()),agentUsed:c.string().optional(),skillsUsed:c.array(c.string()).optional(),startedAt:c.string(),completedAt:c.string()}),jn=c.object({id:c.string(),featureId:c.string(),featureName:c.string(),prdId:c.string().nullable(),version:c.string().optional(),branch:c.string().optional(),prUrl:c.string().optional(),effort:Cn,success:_n.optional(),learnings:Nn,roi:On,rating:Qt,taskOutcomes:c.array(er).optional(),startedAt:c.string(),shippedAt:c.string(),reviewedAt:c.string().optional(),reviewedBy:c.string().optional(),legacy:c.boolean().optional()}),Mn=c.object({totalFeatures:c.number(),averageEstimationAccuracy:c.number(),averageSuccessRate:c.number(),averageROI:c.number(),bySuccessLevel:c.object({exceeded:c.number(),met:c.number(),partial:c.number(),failed:c.number()}),variancePatterns:c.array(c.object({reason:Zt,count:c.number(),averageVariance:c.number()})),topLearnings:c.array(c.object({insight:c.string(),frequency:c.number()}))}),No=c.object({outcomes:c.array(jn),taskOutcomes:c.array(er).optional(),aggregates:Mn.optional(),lastUpdated:c.string(),lastAggregated:c.string().optional()});import{z as v}from"zod";var De=v.enum(["allow","deny","ask"]),Fo=v.enum(["read","write","delete","create"]),Fn=v.record(v.string(),De),st=v.record(v.string(),De),Un=v.object({enabled:v.boolean().default(!0),allowedDomains:v.array(v.string()).optional(),blockedDomains:v.array(v.string()).optional()}),Uo=v.object({bash:Fn.optional(),files:v.object({read:st.optional(),write:st.optional(),delete:st.optional()}).optional(),web:Un.optional(),skills:v.record(v.string(),De).optional(),doomLoop:v.object({enabled:v.boolean().default(!0),maxRetries:v.number().default(3)}).optional(),externalDirectories:De.default("ask")}),$n=["git status*","git log*","git diff*","git branch*","git remote*","ls*","pwd","cat*","head*","tail*","grep*","find*","which*","echo*","node -e*","bun -e*","npm list*","npm view*","npx tsc --noEmit*"],zn=["rm -rf*","rm -r*","git push*","git reset --hard*","git clean*","npm publish*","chmod*","chown*","sudo*","curl*|*sh","wget*|*sh"],Gn=["rm -rf /*","rm -rf ~/*",":(){ :|:& };:*","mkfs*","dd if=*of=/dev/*"];function Xn(){let n={};for(let e of $n)n[e]="allow";for(let e of zn)n[e]="ask";for(let e of Gn)n[e]="deny";return{bash:n,files:{read:{"**/*":"allow"},write:{"**/*":"allow"},delete:{"**/*":"ask"}},web:{enabled:!0},doomLoop:{enabled:!0,maxRetries:3},externalDirectories:"ask"}}o(Xn,"buildDefaultPermissions");var $o=Xn();import{z as N}from"zod";var Jo=N.object({projectId:N.string(),name:N.string(),repoPath:N.string(),description:N.string().optional(),version:N.string().optional(),cliVersion:N.string().optional(),techStack:N.array(N.string()),fileCount:N.number(),commitCount:N.number(),createdAt:N.string(),lastSync:N.string(),lastSyncCommit:N.string().optional(),lastSyncBranch:N.string().optional()});var Ho={techStack:[],fileCount:0,commitCount:0,createdAt:new Date().toISOString(),lastSync:new Date().toISOString()};import{z as l}from"zod";var Jn=l.enum(["planned","active","completed","shipped"]),Hn=l.enum(["low","medium","high"]),Kn=l.enum(["feature","breaking_change","refactor","infrastructure"]),Bn=l.enum(["completed","active","planned"]),qn=l.enum(["planned","active","completed"]),Vn=l.enum(["git","git-branch","manual","prd"]),Yn=l.object({id:l.string(),description:l.string(),completed:l.boolean(),completedAt:l.string().optional()}),Wn=l.object({id:l.string(),name:l.string(),status:Bn,completedAt:l.string().optional()}),Qn=l.object({goal:l.string(),phases:l.array(Wn),successMetrics:l.array(l.string()).optional()}),Zn=l.object({hours:l.number(),minutes:l.number(),totalMinutes:l.number(),display:l.string().optional()}),es=l.object({hash:l.string(),message:l.string(),date:l.string(),author:l.string().optional()}),ts=l.object({hours:l.number(),confidence:l.enum(["low","medium","high"]).optional(),breakdown:l.array(l.object({area:l.string(),hours:l.number()})).optional()}),rs=l.object({hours:l.number().optional(),commits:l.number().optional(),linesAdded:l.number().optional(),linesRemoved:l.number().optional()}),ns=l.object({estimated:ts.nullable(),actual:rs.nullable()}),ss=l.object({totalHours:l.number(),allocatedHours:l.number(),bufferPercent:l.number().optional()}),is=l.object({id:l.string(),name:l.string(),theme:l.string().optional(),goals:l.array(l.string()).optional(),features:l.array(l.string()),capacity:ss.optional(),status:qn,startDate:l.string().optional(),endDate:l.string().optional()}),os=l.object({id:l.string(),name:l.string(),description:l.string().optional(),date:l.string(),status:Jn,impact:Hn,effort:l.string().optional(),progress:l.number(),type:Kn.optional(),roi:l.number().optional(),why:l.array(l.string()).optional(),technicalNotes:l.array(l.string()).optional(),compatibility:l.string().optional(),phase:l.string().optional(),tasks:l.array(Yn),createdAt:l.string(),shippedAt:l.string().optional(),version:l.string().optional(),duration:Zn.optional(),taskCount:l.number().optional(),agent:l.string().optional(),sprintName:l.string().optional(),completedDate:l.string().optional(),prdId:l.string().nullable().optional(),legacy:l.boolean().optional(),inferredFrom:Vn.optional(),quarter:l.string().nullable().optional(),dependencies:l.array(l.string()).optional(),blockedBy:l.array(l.string()).optional(),effortTracking:ns.optional(),valueScore:l.number().optional(),commits:l.array(es).optional(),branch:l.string().optional(),commitsAhead:l.number().optional()}),as=l.object({id:l.string(),title:l.string(),prdId:l.string().nullable().optional(),valueScore:l.number().optional(),effortEstimate:l.number().optional(),reason:l.string().optional()}),Vo=l.object({strategy:Qn.nullable().optional(),features:l.array(os),backlog:l.array(l.union([l.string(),as])),lastUpdated:l.string(),quarters:l.array(is).optional(),generatedFrom:l.enum(["git-history","manual","prd"]).optional(),generatedAt:l.string().optional()});var Yo={date:new Date().toISOString().split("T")[0],status:"planned",impact:"medium",progress:0,tasks:[],createdAt:new Date().toISOString(),prdId:null,legacy:!1,quarter:null};import cs from"node:crypto";import{homedir as ls}from"node:os";import{join as us}from"node:path";function te(){return cs.randomUUID()}o(te,"generateUUID");var ps=us(ls(),".prjct-cli","projects");import{z as _}from"zod";var ia=_.object({sessionId:_.string(),projectId:_.string(),projectPath:_.string(),projectName:_.string().optional(),taskDescription:_.string(),taskStatus:_.enum(["active","paused"]),activeSubtaskIndex:_.number().optional(),subtaskCount:_.number().optional(),branch:_.string().optional(),linearId:_.string().optional(),filesModified:_.array(_.string()).optional(),durationWorkedSec:_.number().optional(),timestamp:_.string(),resumeHint:_.string()});import{z as h}from"zod";var ds=h.enum(["feature","fix","improvement","refactor"]),tr=h.enum(["pass","warning","fail","skipped"]),ms=h.enum(["added","changed","fixed","removed"]),gs=h.object({hours:h.number(),minutes:h.number(),totalMinutes:h.number()}),fs=h.object({filesChanged:h.number().nullable().optional(),linesAdded:h.number().nullable().optional(),linesRemoved:h.number().nullable().optional(),commits:h.number().nullable().optional()}),hs=h.object({description:h.string(),type:ms.optional()}),ys=h.object({lintStatus:tr.nullable().optional(),lintDetails:h.string().optional(),testStatus:tr.nullable().optional(),testDetails:h.string().optional()}),Ss=h.object({hash:h.string().optional(),message:h.string().optional(),branch:h.string().optional()}),Es=h.object({id:h.string(),name:h.string(),version:h.string().nullable().optional(),type:ds,agent:h.string().optional(),description:h.string().optional(),changes:h.array(hs).optional(),codeSnippets:h.array(h.string()).optional(),commit:Ss.optional(),codeMetrics:fs.optional(),qualityMetrics:ys.optional(),quantitativeImpact:h.string().optional(),duration:gs.optional(),tasksCompleted:h.number().nullable().optional(),shippedAt:h.string(),featureId:h.string().optional()}),ca=h.object({shipped:h.array(Es),lastUpdated:h.string()});ge();import{z as a}from"zod";var Ts=a.enum(["low","medium","high","critical"]),_e=a.enum(["feature","bug","improvement","chore"]),xs=a.enum(["active","backlog","previously_active"]),bs=a.enum(["pending","in_progress","completed","blocked","paused","failed","skipped"]),Ps=a.enum(["task_completed","feature_shipped","idea_captured","session_started"]),it=a.object({title:a.string(),description:a.string(),filesChanged:a.array(a.object({path:a.string(),action:a.enum(["created","modified","deleted"])})),whatWasDone:a.array(a.string()).min(1),outputForNextAgent:a.string().min(1),notes:a.string().optional()}),ma=a.object({output:a.string().min(1,"Subtask output is required"),summary:it}),nr=a.object({id:a.string(),description:a.string(),domain:a.string(),agent:a.string(),status:bs,dependsOn:a.array(a.string()),startedAt:a.string().optional(),completedAt:a.string().optional(),output:a.string().optional(),summary:it.optional(),skipReason:a.string().optional(),blockReason:a.string().optional(),estimatedPoints:a.number().optional(),estimatedMinutes:a.number().optional()}),sr=a.object({completed:a.number(),total:a.number(),percentage:a.number()}),ir=a.object({id:a.string(),description:a.string(),type:_e.optional(),startedAt:a.string(),sessionId:a.string(),featureId:a.string().optional(),subtasks:a.array(nr).optional(),currentSubtaskIndex:a.number().optional(),subtaskProgress:sr.optional(),linearId:a.string().optional(),linearUuid:a.string().optional(),estimatedPoints:a.number().optional(),estimatedMinutes:a.number().optional(),modelMetadata:oe.optional()}),rr=a.object({id:a.string(),description:a.string(),status:a.literal("paused"),startedAt:a.string(),pausedAt:a.string(),pauseReason:a.string().optional(),type:_e.optional(),sessionId:a.string().optional(),featureId:a.string().optional(),subtasks:a.array(nr).optional(),currentSubtaskIndex:a.number().optional(),subtaskProgress:sr.optional(),linearId:a.string().optional(),linearUuid:a.string().optional(),estimatedPoints:a.number().optional(),estimatedMinutes:a.number().optional(),modelMetadata:oe.optional()}),Is=a.object({stackConfirmed:a.array(a.string()).optional(),patternsDiscovered:a.array(a.string()).optional(),agentAccuracy:a.array(a.object({agent:a.string(),rating:a.enum(["helpful","neutral","inaccurate"]),note:a.string().optional()})).optional(),issuesEncountered:a.array(a.string()).optional()}),ks=a.object({taskId:a.string(),title:a.string(),classification:_e,startedAt:a.string(),completedAt:a.string(),subtaskCount:a.number(),subtaskSummaries:a.array(it),outcome:a.string(),branchName:a.string(),linearId:a.string().optional(),linearUuid:a.string().optional(),prUrl:a.string().optional(),feedback:Is.optional()}),ga=a.object({currentTask:ir.nullable(),previousTask:rr.nullable().optional(),pausedTasks:a.array(rr).optional(),taskHistory:a.array(ks).optional(),lastUpdated:a.string()}),or=a.object({id:a.string(),description:a.string(),priority:Ts,type:_e,featureId:a.string().optional(),originFeature:a.string().optional(),completed:a.boolean(),completedAt:a.string().optional(),createdAt:a.string(),section:xs,agent:a.string().optional(),groupName:a.string().optional(),groupId:a.string().optional()}),ar=a.object({tasks:a.array(or),lastUpdated:a.string()}),ws=a.object({tasksToday:a.number(),tasksThisWeek:a.number(),streak:a.number(),velocity:a.string(),avgDuration:a.string()}),vs=a.object({type:Ps,description:a.string(),timestamp:a.string(),duration:a.string().optional()}),fa=a.object({projectId:a.string(),currentTask:ir.nullable(),queue:a.array(or),stats:ws,recentActivity:a.array(vs),lastSync:a.string()});import{z as y}from"zod";var As=y.enum(["improving","stable","declining"]),Cs=y.object({sprintNumber:y.number(),startDate:y.string(),endDate:y.string(),pointsCompleted:y.number(),tasksCompleted:y.number(),avgVariance:y.number(),estimationAccuracy:y.number()}),cr=y.object({category:y.string(),avgVariance:y.number(),taskCount:y.number()}),Ea=y.object({totalPoints:y.number(),sprints:y.number(),estimatedDate:y.string()}),Ta=y.object({sprints:y.array(Cs),averageVelocity:y.number(),velocityTrend:As,estimationAccuracy:y.number(),overEstimated:y.array(cr),underEstimated:y.array(cr),lastUpdated:y.string()}),xa=y.object({sprintLengthDays:y.number().min(1).max(90).default(7),startDay:y.enum(["monday","tuesday","wednesday","thursday","friday","saturday","sunday"]).default("monday"),windowSize:y.number().min(1).max(52).default(6),accuracyTolerance:y.number().min(0).max(100).default(20)});var lr={SHIPPED_RETENTION_DAYS:90,IDEA_DORMANT_DAYS:180,QUEUE_COMPLETED_DAYS:7,PAUSED_TASK_DAYS:30,MEMORY_MAX_ENTRIES:500},ot=class{static{o(this,"ArchiveStorage")}archive(e,t){let r=te(),s=I();return P.run(e,"INSERT INTO archives (id, entity_type, entity_id, entity_data, summary, archived_at, reason) VALUES (?, ?, ?, ?, ?, ?, ?)",r,t.entityType,t.entityId,JSON.stringify(t.entityData),t.summary??null,s,t.reason),r}archiveMany(e,t){if(t.length===0)return 0;let r=I();return P.transaction(e,s=>{let i=s.prepare("INSERT INTO archives (id, entity_type, entity_id, entity_data, summary, archived_at, reason) VALUES (?, ?, ?, ?, ?, ?, ?)");for(let u of t)i.run(te(),u.entityType,u.entityId,JSON.stringify(u.entityData),u.summary??null,r,u.reason)}),t.length}getArchived(e,t,r=50){return t?P.query(e,"SELECT * FROM archives WHERE entity_type = ? ORDER BY archived_at DESC LIMIT ?",t,r):P.query(e,"SELECT * FROM archives ORDER BY archived_at DESC LIMIT ?",r)}getStats(e){let t=P.query(e,"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 t){let i=s.entity_type;i in r&&(r[i]=s.count),r.total+=s.count}return r}restore(e,t){let r=P.get(e,"SELECT * FROM archives WHERE id = ?",t);return r?(P.run(e,"DELETE FROM archives WHERE id = ?",t),JSON.parse(r.entity_data)):null}pruneOldArchives(e,t){let r=new Date(Date.now()-t*24*60*60*1e3).toISOString(),s=this.getTotalCount(e);P.run(e,"DELETE FROM archives WHERE archived_at < ?",r);let i=this.getTotalCount(e);return s-i}getTotalCount(e){return P.get(e,"SELECT COUNT(*) as count FROM archives")?.count??0}},ur=new ot;import{z as E}from"zod";var ae={create(n,e){class t extends Error{static{o(this,"TypedError")}errorName;data;isOperational=!0;constructor(s){let i=e.parse(s);super(`${n}: ${JSON.stringify(i)}`),this.name=n,this.errorName=n,this.data=i,Error.captureStackTrace?.(this,this.constructor)}static throw(s){throw new t(s)}static is(s){return s instanceof t&&s.errorName===n}static create(s){return new t(s)}}return t}},Za=ae.create("FileError",E.object({path:E.string(),operation:E.enum(["read","write","delete","create","copy"]),reason:E.string().optional()})),ec=ae.create("ValidationError",E.object({field:E.string(),expected:E.string(),received:E.string().optional(),message:E.string().optional()})),tc=ae.create("PermissionError",E.object({action:E.string(),resource:E.string(),reason:E.string().optional()})),rc=ae.create("TaskError",E.object({taskId:E.string().optional(),operation:E.enum(["create","update","complete","pause","resume","delete"]),reason:E.string()})),nc=ae.create("SessionError",E.object({sessionId:E.string().optional(),reason:E.string()})),sc=ae.create("SyncError",E.object({projectId:E.string().optional(),operation:E.enum(["push","pull","auth","connect"]),reason:E.string()})),at=class extends Error{static{o(this,"PrjctError")}code;isOperational;constructor(e,t="PRJCT_ERROR"){super(e),this.name="PrjctError",this.code=t,this.isOperational=!0,Error.captureStackTrace?.(this,this.constructor)}};function Rs(n){return n instanceof at}o(Rs,"isPrjctError");function pr(n){return Rs(n)||n instanceof Error?n.message:typeof n=="string"?n:"Unknown error"}o(pr,"getErrorMessage");var Le={SESSION_STARTED:"session.started",SESSION_PAUSED:"session.paused",SESSION_RESUMED:"session.resumed",SESSION_COMPLETED:"session.completed",TASK_CREATED:"task.created",TASK_COMPLETED:"task.completed",TASK_UPDATED:"task.updated",FEATURE_ADDED:"feature.added",FEATURE_SHIPPED:"feature.shipped",FEATURE_UPDATED:"feature.updated",IDEA_CAPTURED:"idea.captured",IDEA_PROMOTED:"idea.promoted",SNAPSHOT_CREATED:"snapshot.created",SNAPSHOT_RESTORED:"snapshot.restored",COMMIT_CREATED:"git.commit",PUSH_COMPLETED:"git.push",PROJECT_INITIALIZED:"project.init",PROJECT_SYNCED:"project.sync",ANALYSIS_COMPLETED:"analysis.completed",ALL:"*"};X();var lt={SPINNER_MSG:45,DONE_MSG:50,FAIL_MSG:65,WARN_MSG:65,STEP_MSG:35,PROGRESS_TEXT:25,ISSUE_TITLE:50,FALLBACK_TRUNCATE:50,CLEAR_WIDTH:80};var dr={HISTORY_MAX:100};var ce={error:0,warn:1,info:2,debug:3},Ls=new Set(["1","true","*"]);function Ns(){let n=process.env.PRJCT_DEBUG||process.env.DEBUG||"";if(!n)return{level:-1,name:"disabled"};if(Ls.has(n)||n.includes("prjct"))return{level:ce.debug,name:"debug"};let e=ce[n]??-1,t=e>=0?n:"disabled";return{level:e,name:t}}o(Ns,"getLogLevel");var{level:mr,name:Os}=Ns(),js=o(()=>{},"noop");function Ne(n,e,t){return mr>=n?(...r)=>console[t](e,...r):js}o(Ne,"createLogMethod");var Ms={error:Ne(ce.error,"[prjct:error]","error"),warn:Ne(ce.warn,"[prjct:warn]","warn"),info:Ne(ce.info,"[prjct:info]","log"),debug:Ne(ce.debug,"[prjct:debug]","log"),isEnabled:o(()=>mr>=0,"isEnabled"),level:o(()=>Os,"level")},Oe=Ms;var je=class{static{o(this,"EventBus")}listeners;onceListeners;history;historyLimit;projectId;constructor(){this.listeners=new Map,this.onceListeners=new Map,this.history=[],this.historyLimit=dr.HISTORY_MAX,this.projectId=null}async initialize(e){this.projectId=e}on(e,t){return this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t),()=>this.off(e,t)}once(e,t){return this.onceListeners.has(e)||this.onceListeners.set(e,new Set),this.onceListeners.get(e).add(t),()=>{let r=this.onceListeners.get(e);r&&r.delete(t)}}off(e,t){let r=this.listeners.get(e);r&&r.delete(t)}async emit(e,t={}){let r=new Date().toISOString(),s={type:e,timestamp:r,projectId:this.projectId,...t};this.history.push(s),this.history.length>this.historyLimit&&this.history.shift(),this.projectId&&await this.logEvent(s);let i=this.getMatchingListeners(e);(await Promise.allSettled(i.map(C=>this.executeCallback(C,s)))).forEach(C=>{C.status==="rejected"&&Oe.error(`Event listener error for ${e}:`,C.reason)});let p=this.onceListeners.get(e);if(p){for(let C of p)await this.executeCallback(C,s);this.onceListeners.delete(e)}let x=this.onceListeners.get(Le.ALL);if(x)for(let C of x)await this.executeCallback(C,s)}getMatchingListeners(e){let t=[],r=this.listeners.get(e);r&&t.push(...r);let s=this.listeners.get(Le.ALL);s&&t.push(...s);let i=e.split(".")[0],u=this.listeners.get(`${i}.*`);return u&&t.push(...u),t}async executeCallback(e,t){try{let r=e(t);r instanceof Promise&&await r}catch(r){throw Oe.error("Event callback error:",r),r}}async logEvent(e){try{P.appendEvent(this.projectId,e.type,e)}catch(t){Oe.debug("Failed to log event:",pr(t))}}getHistory(e=10,t=null){let r=this.history;return t&&(r=r.filter(s=>s.type===t||s.type.startsWith(t))),r.slice(-e)}clear(){this.listeners.clear(),this.onceListeners.clear()}flush(){this.history=[],this.onceListeners.clear()}removeAllListeners(e){e?(this.listeners.delete(e),this.onceListeners.delete(e)):(this.listeners.clear(),this.onceListeners.clear())}listenerCount(e){let t=this.listeners.get(e);return t?t.size:0}getRegisteredEvents(){return Array.from(this.listeners.keys())}},Fs=new je;me();var Me=class{static{o(this,"SyncEventBus")}async publish(e){let t=W.getSyncPendingPath(e.projectId),r=await ke(t,[])??[];r.push(e),await we(t,r)}async getPending(e){let t=W.getSyncPendingPath(e);return await ke(t,[])??[]}async clearPending(e){let t=W.getSyncPendingPath(e);await we(t,[])}async updateLastSync(e){let t=W.getLastSyncPath(e),r={timestamp:I(),success:!0};await we(t,r)}async getLastSync(e){let t=W.getLastSyncPath(e);return await ke(t,null)}},ut=new Me;var Fe=class{static{o(this,"StorageManager")}filename;cache;constructor(e,t){this.filename=e,this.cache=new K({ttl:5e3,maxSize:50})}getStoreKey(){return this.filename.replace(".json","")}async read(e){let t=this.cache.get(e);if(t!==null)return t;try{let r=P.getDoc(e,this.getStoreKey());if(r!==null)return this.cache.set(e,r),r}catch{}return this.getDefault()}async write(e,t){P.setDoc(e,this.getStoreKey(),t),this.cache.set(e,t)}async update(e,t){let r=await this.read(e),s=t(r);return await this.write(e,s),s}async publishEvent(e,t,r){let s={type:t,path:[this.filename.replace(".json","")],data:r,timestamp:I(),projectId:e};await ut.publish(s)}async publishEntityEvent(e,t,r,s){let i=`${t}.${r}`,u={...s,timestamp:I()};await this.publishEvent(e,i,u)}async exists(e){try{return P.hasDoc(e,this.getStoreKey())}catch{return!1}}clearCache(e){e?this.cache.delete(e):this.cache.clear()}getCacheStats(){return this.cache.stats()}};var pt=class extends Fe{static{o(this,"QueueStorage")}constructor(){super("queue.json",ar)}getDefault(){return{tasks:[],lastUpdated:""}}getEventType(e){return`queue.${e}d`}async getTasks(e){return(await this.read(e)).tasks}async getActiveTasks(e){return(await this.read(e)).tasks.filter(r=>r.section==="active"&&!r.completed)}async getBacklog(e){return(await this.read(e)).tasks.filter(r=>r.section==="backlog"&&!r.completed)}async getNextTask(e){let t=await this.getActiveTasks(e);return this.sortTasks(t)[0]||null}async addTask(e,t){let r={...t,id:te(),createdAt:I(),completed:!1};return await this.update(e,s=>({tasks:[...s.tasks,r],lastUpdated:I()})),await this.publishEvent(e,"queue.task_added",{taskId:r.id,description:r.description,priority:r.priority,section:r.section}),r}async addTasks(e,t){let r=I(),s=t.map(i=>({...i,id:te(),createdAt:r,completed:!1}));return await this.update(e,i=>({tasks:[...i.tasks,...s],lastUpdated:r})),await this.publishEvent(e,"queue.tasks_added",{count:s.length,tasks:s.map(i=>({id:i.id,description:i.description}))}),s}async removeTask(e,t){await this.update(e,r=>({tasks:r.tasks.filter(s=>s.id!==t),lastUpdated:I()})),await this.publishEvent(e,"queue.task_removed",{taskId:t})}async completeTask(e,t){let r=null;if(await this.update(e,s=>({tasks:s.tasks.map(u=>u.id===t?(r={...u,completed:!0,completedAt:I()},r):u),lastUpdated:I()})),r){let s=r;await this.publishEvent(e,"queue.task_completed",{taskId:t,description:s.description,completedAt:s.completedAt})}return r}async moveToSection(e,t,r){await this.update(e,s=>({tasks:s.tasks.map(i=>i.id===t?{...i,section:r}:i),lastUpdated:I()}))}async setPriority(e,t,r){await this.update(e,s=>({tasks:s.tasks.map(i=>i.id===t?{...i,priority:r}:i),lastUpdated:I()}))}async clearCompleted(e){let r=(await this.read(e)).tasks.filter(s=>s.completed).length;return await this.update(e,s=>({tasks:s.tasks.filter(i=>!i.completed),lastUpdated:I()})),r}async removeStaleCompleted(e){let t=await this.read(e),r=wt(lr.QUEUE_COMPLETED_DAYS),s=t.tasks.filter(u=>u.completed&&u.completedAt&&new Date(u.completedAt)<r);if(s.length===0)return 0;ur.archiveMany(e,s.map(u=>({entityType:"queue_task",entityId:u.id,entityData:u,summary:u.description,reason:"age"})));let i=new Set(s.map(u=>u.id));return await this.update(e,u=>({tasks:u.tasks.filter(p=>!i.has(p.id)),lastUpdated:I()})),await this.publishEvent(e,"queue.stale_removed",{count:s.length}),s.length}sortTasks(e){let t={critical:0,high:1,medium:2,low:3},r={active:0,previously_active:1,backlog:2};return[...e].sort((s,i)=>{let u=r[s.section]-r[i.section];if(u!==0)return u;let p=t[s.priority]-t[i.priority];return p!==0?p:new Date(s.createdAt).getTime()-new Date(i.createdAt).getTime()})}},dt=new pt;X();var Us=/\b[A-Z]+-\d+\b/,gr=1800*1e3,Ue=class{static{o(this,"LinearSync")}async pullAll(e){let t=new Date().toISOString(),r=[];try{let s=await T.fetchAssignedIssues({limit:100}),i={};for(let p of s)try{i[p.externalId]=this.toCachedIssue(p,t)}catch(x){r.push({issueId:p.externalId||p.id,error:O(x)})}let u={provider:"linear",lastSync:t,staleAfter:gr,issues:i};return P.setDoc(e,"issues",u),{provider:"linear",fetched:s.length,updated:Object.keys(i).length,errors:r,timestamp:t}}catch(s){return r.push({issueId:"all",error:O(s)}),{provider:"linear",fetched:0,updated:0,errors:r,timestamp:t}}}async getIssue(e,t){let r=this.loadIssues(e);if(r?.issues[t]){let s=r.issues[t],i=new Date(s.fetchedAt).getTime(),u=Date.now(),p=600*1e3;if(u-i<p)return s}try{let s=await T.fetchIssue(t);if(!s)return null;let i=new Date().toISOString(),u=this.toCachedIssue(s,i);return this.updateIssueInCache(e,t,u),u}catch{return r?.issues[t]?r.issues[t]:null}}async getIssueLocal(e,t){return this.loadIssues(e)?.issues[t]||null}async pushStatus(e,t,r){r==="in_progress"?await T.markInProgress(t):r==="done"&&await T.markDone(t);let s=this.loadIssues(e);if(s?.issues[t]){let i=r==="done"?"done":"in_progress";s.issues[t].status=i,s.issues[t].fetchedAt=new Date().toISOString(),this.saveIssues(e,s)}}async isStale(e){let t=this.loadIssues(e);if(!t||!t.lastSync)return!0;let r=new Date(t.lastSync).getTime(),s=Date.now(),i=t.staleAfter||gr;return s-r>i}async getSyncStatus(e){let t=this.loadIssues(e);return t?{hasCache:!0,lastSync:t.lastSync||null,issueCount:Object.keys(t.issues).length,isStale:await this.isStale(e)}:{hasCache:!1,lastSync:null,issueCount:0,isStale:!0}}async listCachedIssues(e){let t=this.loadIssues(e);return t?Object.values(t.issues):[]}async reconcileQueue(e){let t=this.loadIssues(e);if(!t)return 0;let r=new Set;for(let[u,p]of Object.entries(t.issues))(p.status==="done"||p.status==="in_review")&&r.add(u);if(r.size===0)return 0;let s=await dt.getTasks(e),i=0;for(let u of s){if(u.completed)continue;let p=u.description.match(Us);p&&r.has(p[0])&&(await dt.completeTask(e,u.id),i++)}return i}loadIssues(e){try{return P.getDoc(e,"issues")}catch{return null}}saveIssues(e,t){P.setDoc(e,"issues",t)}updateIssueInCache(e,t,r){let s=this.loadIssues(e);s||(s=It("linear")),s.issues[t]=r,this.saveIssues(e,s)}toCachedIssue(e,t){return{id:e.id,identifier:e.externalId,title:e.title,description:e.description,status:e.status,priority:e.priority,type:e.type,assignee:e.assignee,labels:e.labels,team:e.team,project:e.project,url:e.url,createdAt:e.createdAt,updatedAt:e.updatedAt,fetchedAt:t}}},le=new Ue;X();import M from"chalk";fe();import re from"chalk";var fr=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],$s=80,zs={name:"prjct",icon:"\u26A1",signature:"\u26A1 prjct",spinner:{frames:fr,speed:$s},cli:{header:o(()=>`${re.cyan.bold("\u26A1")} ${re.cyan("prjct")}`,"header"),footer:o(()=>re.dim("\u26A1 prjct"),"footer"),spin:o((n,e)=>`${re.cyan("\u26A1")} ${re.cyan("prjct")} ${re.cyan(fr[n%10])} ${re.dim(e||"")}`,"spin")},template:{header:"\u26A1 prjct",footer:"\u26A1 prjct"},commitFooter:"Generated with [p/](https://www.prjct.app/)",urls:{website:"https://prjct.app",docs:"https://prjct.app/docs"},getCommitFooter:o((n="claude")=>Ae(n).commitFooter,"getCommitFooter"),getSignature:o((n="claude")=>Ae(n).signature,"getSignature")},mt=zs;var jl=mt.spinner.frames,Ml=mt.spinner.speed,Xs={silent:{maxLines:0,maxCharsPerLine:0,showMetrics:!1},minimal:{maxLines:1,maxCharsPerLine:65,showMetrics:!1},compact:{maxLines:4,maxCharsPerLine:80,showMetrics:!0},verbose:{maxLines:1/0,maxCharsPerLine:1/0,showMetrics:!0}},ye="compact";function hr(n){ye=n}o(hr,"setOutputTier");function ft(){return Xs[ye]}o(ft,"getTierConfig");var Fl={success:M.green("\u2713"),fail:M.red("\u2717"),warn:M.yellow("\u26A0"),info:M.blue("\u2139"),debug:M.dim("\u{1F527}"),bullet:M.dim("\u2022"),arrow:M.dim("\u2192"),check:M.green("\u2713"),cross:M.red("\u2717"),spinner:M.cyan("\u25D0")};var $e=o((n,e)=>{let t=e??(ft().maxCharsPerLine||lt.FALLBACK_TRUNCATE);return n&&n.length>t?`${n.slice(0,t-1)}\u2026`:n||""},"truncate");function gt(n,e){let t=e??ft().maxLines;if(t===1/0||t===0)return n;let r=n.split(`
344
- `);if(r.length<=t)return n;let s=r.slice(0,t),i=r.length-t;return`${s.join(`
345
- `)}
346
- ${M.dim(`...${i} more lines`)}`}o(gt,"limitLines");function yr(n){let e=ft();if(ye==="silent")return"";if(ye==="verbose")return JSON.stringify(n,null,2);if(typeof n!="object"||n===null)return $e(String(n),e.maxCharsPerLine);let t=n;if("identifier"in t&&"title"in t){let i=[];return i.push(`${t.identifier}: ${$e(String(t.title),e.maxCharsPerLine-10)}`),t.status&&i.push(`Status: ${t.status}`),t.priority&&t.priority!=="none"&&i.push(`Priority: ${t.priority}`),t.url&&ye==="compact"&&i.push(M.dim(String(t.url))),gt(i.join(`
347
- `),e.maxLines)}if("issues"in t&&Array.isArray(t.issues)){let i=t.issues,u=i.slice(0,e.maxLines).map(p=>{let x=p.priority&&p.priority!=="none"?` [${p.priority}]`:"";return`${p.identifier} ${$e(String(p.title),lt.ISSUE_TITLE)}${x}`});return i.length>e.maxLines&&u.push(M.dim(`...${i.length-e.maxLines} more`)),u.join(`
348
- `)}let s=["id","name","title","status","message","success","error"].filter(i=>i in t);return s.length>0?gt(s.map(i=>`${i}: ${$e(String(t[i]),e.maxCharsPerLine-i.length-2)}`).join(`
349
- `),e.maxLines):gt(JSON.stringify(n,null,2),e.maxLines)}o(yr,"formatForHuman");X();me();be();import ht from"node:fs/promises";import Js from"node:os";import Sr from"node:path";function Er(n){return Sr.join(Js.homedir(),".prjct-cli","projects",n,"config","credentials.json")}o(Er,"getCredentialsPath");async function Q(n){let e=Er(n);if(!await k(e))return{};try{return JSON.parse(await ht.readFile(e,"utf-8"))}catch(t){return console.error("[project-credentials] Failed to read credentials:",O(t)),{}}}o(Q,"getProjectCredentials");async function Tr(n,e){let t=Er(n),r=Sr.dirname(t);await k(r)||await ht.mkdir(r,{recursive:!0});let s=await Q(n);s.linear=e,await ht.writeFile(t,JSON.stringify(s,null,2))}o(Tr,"setLinearCredentials");async function yt(n){let e=await Q(n);return e.linear?.apiKey?e.linear.apiKey:ie("linear-api-key")}o(yt,"getLinearApiKey");async function xr(n){if((await Q(n)).linear?.apiKey)return"project";let{getCredentialWithSource:t}=await Promise.resolve().then(()=>(be(),xt)),r=await t("linear-api-key");return r.value?r.source==="keychain"?"keychain":"env":"none"}o(xr,"getCredentialSource");var B=process.argv.slice(2),ze=B.indexOf("--project"),A=null;ze!==-1&&B[ze+1]&&(A=B[ze+1],B.splice(ze,2));var Pr=B.indexOf("--json"),Z=Pr!==-1;Z&&B.splice(Pr,1);var Ir=B.indexOf("--verbose"),Hs=Ir!==-1;Hs&&(B.splice(Ir,1),hr("verbose"));var[br,...L]=B;function R(n){console.log(Z?JSON.stringify(n,null,2):yr(n))}o(R,"output");function S(n,e=1){console.error(Z?JSON.stringify({error:n}):`Error: ${n}`),process.exit(e)}o(S,"error");async function G(){A||S("No --project specified. Usage: linear.ts --project <projectId> <command>");let n=await yt(A);n||S("Linear not configured. Run: p. linear setup");let e=await Q(A);await T.initializeFromApiKey(n,e.linear?.teamId)}o(G,"initFromProject");async function Ks(){try{switch(br){case"setup":{A||S("--project required for setup");let n=L[0],e=L[1];n||S("API key required. Usage: setup <apiKey> [teamId]"),await T.initializeFromApiKey(n,e);let t=await T.getTeams();t.length===0&&S("No teams found. Check your API key permissions.");let r=e,s;if(!r&&t.length===1)r=t[0].id,s=t[0].key;else if(r){let i=t.find(u=>u.id===r||u.key===r);i&&(r=i.id,s=i.key)}await Tr(A,{apiKey:n,teamId:r,teamKey:s,setupAt:new Date().toISOString()}),R({success:!0,teams:t,defaultTeam:r?{id:r,key:s}:null});break}case"list":{await G();let n=L[0]?parseInt(L[0],10):20,e=await Q(A),t;e.linear?.teamId?t=await T.fetchTeamIssues(e.linear.teamId,{limit:n}):t=await T.fetchAssignedIssues({limit:n});let r=t.map(s=>({id:s.id,identifier:s.externalId,title:s.title,status:s.status,priority:s.priority,url:s.url}));if(Z)R({count:t.length,issues:r});else{console.log(`Your issues (${t.length}):`);for(let s of r.slice(0,10)){let i=s.priority&&s.priority!=="none"?` [${s.priority}]`:"";console.log(` ${s.identifier} ${s.title.slice(0,50)}${i}`)}t.length>10&&console.log(` ...${t.length-10} more`)}break}case"list-team":{await G();let n=L[0],e=L[1]?parseInt(L[1],10):20;n||S("Team ID required. Usage: list-team <teamId> [limit]");let t=await T.fetchTeamIssues(n,{limit:e});R({count:t.length,issues:t.map(r=>({id:r.id,identifier:r.externalId,title:r.title,status:r.status,priority:r.priority,url:r.url}))});break}case"get":{await G();let n=L[0];n||S("Issue ID required. Usage: get <id>");let e=await T.fetchIssue(n);if(e||S(`Issue not found: ${n}`),Z)R(e);else{if(console.log(`${e.externalId}: ${e.title}`),console.log(`Status: ${e.status} | Priority: ${e.priority||"none"}`),e.description){let t=e.description.slice(0,200);console.log(`
350
- ${t}${e.description.length>200?"...":""}`)}console.log(`
351
- ${e.url}`)}break}case"get-local":{A||S("--project required for get-local");let n=L[0];n||S("Issue ID required. Usage: get-local <id>");let e=await le.getIssueLocal(A,n);e||S(`Issue not in local cache: ${n}. Run 'sync' first.`),R(e);break}case"sync":{A||S("--project required for sync"),await G();let n=await le.pullAll(A),e=await le.reconcileQueue(A);R({success:n.errors.length===0,...n,reconciled:e});break}case"sync-status":{A||S("--project required for sync-status");let n=await le.getSyncStatus(A);R(n);break}case"create":{await G();let n=L[0];n||S(`JSON input required. Usage: create '{"title":"...", "teamId":"..."}'`);let e;try{e=JSON.parse(n)}catch{S(`Invalid JSON: ${n}`)}if(e.title||S("title is required"),!e.teamId){let r=await Q(A);r.linear?.teamId?e.teamId=r.linear.teamId:S("teamId is required (no default team configured)")}let t=await T.createIssue(e);R(t);break}case"update":{await G();let n=L[0],e=L[1];n||S(`Issue ID required. Usage: update <id> '{"description":"..."}'`),e||S(`JSON input required. Usage: update <id> '{"description":"..."}'`);let t;try{t=JSON.parse(e)}catch{S(`Invalid JSON: ${e}`)}let r=await T.updateIssue(n,t);R(r);break}case"start":{await G();let n=L[0];n||S("Issue ID required. Usage: start <id>"),await T.markInProgress(n),R({success:!0,id:n,status:"in_progress"});break}case"done":{await G();let n=L[0];n||S("Issue ID required. Usage: done <id>"),await T.markDone(n),R({success:!0,id:n,status:"done"});break}case"comment":{await G();let n=L[0],e=L.slice(1).join(" ");n||S("Issue ID required. Usage: comment <id> <text>"),e||S("Comment text required. Usage: comment <id> <text>"),await T.addComment(n,e),R({success:!0,id:n});break}case"teams":{await G();let n=await T.getTeams();R({count:n.length,teams:n});break}case"projects":{await G();let n=await T.getProjects();R({count:n.length,projects:n});break}case"status":{A||S("--project required for status");let n=await xr(A),e=await yt(A),t=await Q(A);if(!e){Z?R({configured:!1,source:"none",message:"Linear not configured"}):(console.log("Linear: Not configured"),console.log("Run: p. linear setup"));break}try{await T.initializeFromApiKey(e,t.linear?.teamId);let r=await T.getTeams();Z?R({configured:!0,source:n,teamId:t.linear?.teamId,teamKey:t.linear?.teamKey,teamsAvailable:r.length}):(console.log("Linear: Connected"),t.linear?.teamKey&&console.log(`Team: ${t.linear.teamKey}`),console.log(`Teams: ${r.length} available`))}catch(r){Z?R({configured:!0,source:n,connectionError:O(r)}):(console.log("Linear: Connection error"),console.log(`Error: ${O(r)}`))}break}case"help":case"--help":case"-h":case void 0:{R({usage:"linear.ts --project <projectId> <command> [args...]",commands:{setup:"setup <apiKey> [teamId] - Store API key",list:"list [limit] - List my assigned issues","list-team":"list-team <teamId> [limit] - List team issues",get:"get <id> - Get issue by ID or identifier","get-local":"get-local <id> - Get from local cache (no API)",sync:"sync - Pull all assigned issues to local storage","sync-status":"sync-status - Check local cache status",create:"create <json> - Create issue",update:"update <id> <json> - Update issue",start:"start <id> - Mark as in progress",done:"done <id> - Mark as done",comment:"comment <id> <text> - Add comment",teams:"teams - List available teams",projects:"projects - List available projects",status:"status - Check connection"}});break}default:S(`Unknown command: ${br}. Use --help to see available commands.`)}}catch(n){S(O(n))}}o(Ks,"main");Ks();
8
+ var w=Object.defineProperty;var r=(e,n)=>w(e,"name",{value:n,configurable:!0});function i(e){return e instanceof Error?e.message:typeof e=="string"?e:"Unknown error"}r(i,"getErrorMessage");import p from"node:fs/promises";import C from"node:os";import l from"node:path";var M={linear:{command:"npx",args:["-y","mcp-remote","https://mcp.linear.app/mcp"],description:"Linear MCP server (OAuth)"},jira:{command:"npx",args:["-y","mcp-remote","https://mcp.atlassian.com/v1/mcp"],description:"Atlassian MCP server for Jira (OAuth)"}};function o(){return process.env.PRJCT_TEST_MODE==="1"?l.join(C.tmpdir(),"prjct-context7-test","mcp.json"):l.join(C.homedir(),".claude","mcp.json")}r(o,"getClaudeMcpConfigPath");async function P(e=o()){try{let n=await p.readFile(e,"utf-8");return JSON.parse(n)}catch(n){let t=i(n).toLowerCase();if(t.includes("no such file")||t.includes("enoent"))return{};throw new Error(`Failed to read MCP config at ${e}: ${i(n)}`)}}r(P,"readMcpConfig");async function x(e,n=o()){await p.mkdir(l.dirname(n),{recursive:!0}),await p.writeFile(n,JSON.stringify(e,null,2),"utf-8")}r(x,"writeMcpConfig");async function v(e,n,t=o()){let a=await P(t),u={...a.mcpServers||{}},y=u[e];u[e]=n,a.mcpServers=u;let S=JSON.stringify(y)!==JSON.stringify(n);return await x(a,t),{path:t,changed:S}}r(v,"upsertMcpServer");async function d(e,n=o()){return!!(await P(n)).mcpServers?.[e]}r(d,"hasMcpServer");var s=process.argv.slice(2),h=s.indexOf("--json"),m=h!==-1;m&&s.splice(h,1);var E=s.indexOf("--md");E!==-1&&s.splice(E,1);var[g,...k]=s;function c(e){if(m){console.log(JSON.stringify(e,null,2));return}if(typeof e=="string"){console.log(e);return}console.log(JSON.stringify(e,null,2))}r(c,"output");function f(e,n=1){console.error(m?JSON.stringify({error:e}):`Error: ${e}`),process.exit(n)}r(f,"error");async function O(){let e=await v("linear",M.linear);c({success:!0,provider:"linear",mode:"mcp",path:e.path,updated:e.changed,nextSteps:["Open your MCP-enabled AI client.","Run any Linear operation to complete OAuth authorization when prompted."]})}r(O,"setup");async function R(){let e=o(),n=await d("linear",e);c({provider:"linear",mode:"mcp",configured:n,path:e,hint:n?"Linear MCP is configured. OAuth happens inside your AI client.":"Run `prjct linear setup` to configure Linear MCP."})}r(R,"status");async function b(e,n){let t=o();await d("linear",t)||f("Linear MCP is not configured. Run `prjct linear setup` first."),c({success:!0,provider:"linear",mode:"mcp",delegated:!0,command:e,args:n,hint:"Run this operation using Linear MCP tools in your current AI client session.",nextSteps:["Open your MCP-enabled AI client/session.",`Execute the Linear MCP operation for "${e}".`]})}r(b,"runMcpOperation");async function j(){try{switch(g){case"setup":await O();break;case"status":await R();break;case"help":case"--help":case"-h":case void 0:c({usage:"prjct linear <command>",commands:{setup:"Configure Linear MCP server",status:"Check Linear MCP configuration",sync:"Delegate issue sync via MCP tools",list:"Delegate issue listing via MCP tools",get:"Delegate issue retrieval via MCP tools",create:"Delegate issue creation via MCP tools",update:"Delegate issue update via MCP tools",start:"Delegate status transition to in-progress via MCP tools",done:"Delegate status transition to done via MCP tools",comment:"Delegate comment creation via MCP tools"},note:"Linear is MCP-only."});break;case"sync":case"list":case"get":case"create":case"update":case"start":case"done":case"comment":case"teams":case"projects":await b(g,k);break;default:f(`Unknown command: ${g}. Use --help to see available commands.`)}}catch(e){f(i(e))}}r(j,"main");j();