taskgraph-ai 0.49.1 → 0.52.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/README.md +49 -27
  2. package/dist/ai-services-unified-CQGTT-i4.js +3 -0
  3. package/dist/ai-services-unified-i_GZ3WhA.js +1 -0
  4. package/dist/{commands-CceFmRJA.js → commands-D4fCcXpl.js} +86 -86
  5. package/dist/config-manager-CMb8CR7Q.js +1 -0
  6. package/dist/config-manager-CvMw_24E.js +1 -0
  7. package/dist/dependency-manager-B9utPujC.js +961 -0
  8. package/dist/git-utils-BFUgMf2g.js +1 -0
  9. package/dist/{git-utils-DllbRE35.js → git-utils-CrYiSKu0.js} +1 -1
  10. package/dist/{init-wtXaFE45.js → init-BkYF2xYP.js} +64 -388
  11. package/dist/mcp-server.js +5 -5
  12. package/dist/research-Bol2O66r.js +1 -0
  13. package/dist/response-language-BKY-k633.js +1 -0
  14. package/dist/{response-language-BHhde6n_.js → response-language-Dnr7IBrP.js} +1 -1
  15. package/dist/src-O6Nu6TVe.js +203 -0
  16. package/dist/tag-management-Du0gQ3h8.js +1 -0
  17. package/dist/task-manager-CAZrTo7j.js +1 -0
  18. package/dist/taskgraph.js +1 -1
  19. package/dist/update-subtask-by-id-D2oia6KG.js +1 -0
  20. package/dist/update-task-by-id-BvEvVUjJ.js +1 -0
  21. package/dist/utils-Bdg3bcKY.js +1 -0
  22. package/package.json +6 -6
  23. package/dist/ai-services-unified--6CT6QUI.js +0 -1
  24. package/dist/ai-services-unified-D8PahWkz.js +0 -3
  25. package/dist/config-manager-CvDCaURh.js +0 -1
  26. package/dist/config-manager-DD5sEcpv.js +0 -270
  27. package/dist/dependency-manager-B7SaMC6u.js +0 -966
  28. package/dist/git-utils-PBP1PRVP.js +0 -1
  29. package/dist/research-BRpAIbWg.js +0 -1
  30. package/dist/response-language-Dz-rFnaJ.js +0 -1
  31. package/dist/sentry-DNoFrfjb.js +0 -1
  32. package/dist/tag-management-BEKnBGXA.js +0 -1
  33. package/dist/task-manager-BQkOlw_W.js +0 -1
  34. package/dist/update-subtask-by-id-BOFRADbR.js +0 -1
  35. package/dist/update-task-by-id-DTHqRii_.js +0 -1
  36. package/dist/utils-DYpucGVy.js +0 -1
@@ -1,35 +1,35 @@
1
- import"./ai-services-unified-D8PahWkz.js";import{At as e,Ct as t,E as n,Ft as r,L as i,Mt as a,X as o,c as s,it as c,jt as l,kt as u,s as d,t as f,ut as p,wt as m,yt as h}from"./config-manager-DD5sEcpv.js";import"./git-utils-DllbRE35.js";import"./sentry-DNoFrfjb.js";import{$ as ee,A as te,B as g,C as ne,D as re,E as _,F as v,G as ie,H as ae,J as oe,K as se,M as ce,N as le,O as y,P as ue,R as de,S as fe,U as b,V as pe,W as x,X as me,Y as he,Z as ge,_ as _e,b as S,c as C,ct as w,d as T,et as E,f as D,g as O,h as k,i as A,it as j,j as M,l as N,lt as P,m as F,n as I,o as ve,ot as ye,p as L,q as be,r as xe,s as Se,st as Ce,t as we,u as Te,ut as Ee,v as R,x as De,y as Oe,z as ke}from"./dependency-manager-B7SaMC6u.js";import{t as Ae}from"./response-language-BHhde6n_.js";import{n as z,r as je,t as Me}from"./init-wtXaFE45.js";import B from"chalk";import V from"fs";import H from"path";import U from"boxen";import{Command as Ne,Option as W}from"commander";import G from"inquirer";const K={AUTHENTICATION:`authentication`,VALIDATION:`validation`,NETWORK:`network`,API:`api`,FILE_SYSTEM:`file_system`,TASK:`task`,PERMISSION:`permission`,TIMEOUT:`timeout`,GENERIC:`generic`},q=[/\b[A-Za-z0-9_-]{20,}\b/g,/sk-[A-Za-z0-9]{32,}/g,/api[_-]?key[:\s=]+[^\s]+/gi,/bearer\s+[^\s]+/gi,/token[:\s=]+[^\s]+/gi,/\/Users\/[^/]+/g,/C:\\Users\\[^\\]+/g,/\/home\/[^/]+/g,/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g,/https?:\/\/[^:]+:[^@]+@/g];function J(e){if(!e||typeof e!=`string`)return e;let t=e;for(let e of q)t=t.replace(e,`***REDACTED***`);return t}function Pe(e){if(!e)return K.GENERIC;let t=(e.message||``).toLowerCase(),n=(e.code||``).toLowerCase();return t.includes(`auth`)||t.includes(`unauthorized`)||t.includes(`forbidden`)||t.includes(`api key`)||t.includes(`token`)||n.includes(`auth`)?K.AUTHENTICATION:t.includes(`invalid`)||t.includes(`validation`)||t.includes(`required`)||t.includes(`must be`)||n.includes(`validation`)?K.VALIDATION:t.includes(`network`)||t.includes(`connection`)||t.includes(`econnrefused`)||t.includes(`enotfound`)||n.includes(`network`)||n.includes(`econnrefused`)||n.includes(`enotfound`)?K.NETWORK:t.includes(`timeout`)||t.includes(`timed out`)||n.includes(`timeout`)?K.TIMEOUT:t.includes(`api`)||t.includes(`rate limit`)||t.includes(`quota`)||n.includes(`api`)?K.API:t.includes(`enoent`)||t.includes(`eacces`)||t.includes(`file`)||t.includes(`directory`)||n.includes(`enoent`)||n.includes(`eacces`)?K.FILE_SYSTEM:t.includes(`permission`)||t.includes(`access denied`)||n.includes(`eperm`)?K.PERMISSION:t.includes(`task`)||t.includes(`subtask`)?K.TASK:K.GENERIC}function Fe(e,t,n){let r=[],i=(t.message||``).toLowerCase();switch(e){case K.AUTHENTICATION:i.includes(`api key`)?(r.push(`Check that your API key is correctly set in the .env file`),r.push(`Verify the API key has not expired or been revoked`)):i.includes(`token`)?(r.push(`Your authentication token may have expired`),r.push(`Try running: tm auth refresh`)):(r.push(`Verify your credentials are correctly configured`),r.push(`Check the authentication status with: tm auth status`));break;case K.VALIDATION:i.includes(`brief id`)?(r.push(`Brief IDs are case-insensitive (e.g., "ham32" = "HAM-32")`),r.push(`Check the brief ID format: usually LETTERS-NUMBERS`)):i.includes(`task id`)||i.includes(`invalid id`)?(r.push(`Task IDs should be numbers (e.g., 1, 2, 3)`),r.push(`Subtask IDs use dot notation (e.g., 1.1, 2.3)`)):(r.push(`Check that all required parameters are provided`),r.push(`Verify parameter values match expected formats`));break;case K.NETWORK:i.includes(`econnrefused`)?(r.push(`Could not connect to the server`),r.push(`Check your internet connection`),r.push(`Verify the API endpoint URL is correct`)):i.includes(`enotfound`)?(r.push(`Could not resolve the server hostname`),r.push(`Check your internet connection`)):(r.push(`Check your network connection`),r.push(`Verify firewall settings are not blocking the request`));break;case K.TIMEOUT:r.push(`The operation took too long to complete`),r.push(`Try again with a simpler request`),r.push(`Check your network speed and stability`);break;case K.API:i.includes(`rate limit`)?(r.push(`You have exceeded the API rate limit`),r.push(`Wait a few minutes before trying again`)):i.includes(`quota`)?(r.push(`You have reached your API quota`),r.push(`Check your account usage and limits`)):(r.push(`The API returned an error`),r.push(`Try again in a few moments`));break;case K.FILE_SYSTEM:i.includes(`enoent`)?(r.push(`The specified file or directory does not exist`),r.push(`Check the file path and ensure it is correct`),n.includes(`tasks.json`)&&r.push(`Initialize the project with: tm init`)):i.includes(`eacces`)?(r.push(`Permission denied to access the file`),r.push(`Check file permissions or run with appropriate privileges`)):r.push(`Check that the file or directory exists and is accessible`);break;case K.PERMISSION:r.push(`You do not have permission to perform this operation`),r.push(`Check file/directory permissions`),r.push(`You may need elevated privileges (sudo)`);break;case K.TASK:i.includes(`not found`)?(r.push(`The specified task does not exist`),r.push(`Use: tm list to see all available tasks`)):i.includes(`dependency`)||i.includes(`circular`)?(r.push(`Task dependencies form a circular reference`),r.push(`Use: tm validate-dependencies to identify issues`)):(r.push(`Check that the task ID is correct`),r.push(`Use: tm show <id> to view task details`));break;default:r.push(`Check the error message for specific details`),n&&r.push(`Operation failed while: ${n}`)}return r.slice(0,2)}function Ie(e,t={}){let{context:n=``,debug:r=!1,command:i=``}=t;typeof e==`string`&&(e=Error(e)),(!e||typeof e!=`object`)&&(e=Error(`An unknown error occurred`));let a=J(e.message||`Unknown error`),o=Pe(e),s=Fe(o,e,n);return{type:o,message:a,context:n||`Unknown operation`,hints:s,command:i||null,code:e.code||null,stack:r?J(e.stack):null}}function Y(e,n={}){let r=Ie(e,n),i=B.red.bold(`✗ Error
1
+ import"./ai-services-unified-CQGTT-i4.js";import"./src-O6Nu6TVe.js";import{At as e,Dt as t,F as n,J as r,Nt as i,Ot as a,St as o,T as s,_t as c,ct as l,kt as u,nt as d,o as f,s as p,t as m,xt as h}from"./config-manager-CMb8CR7Q.js";import"./git-utils-CrYiSKu0.js";import{$ as ee,A as te,B as g,C as ne,D as re,E as _,F as v,G as ie,H as ae,J as oe,K as se,M as ce,N as le,O as y,P as ue,R as de,S as fe,U as b,V as pe,W as x,X as me,Y as he,Z as ge,_ as _e,b as S,c as C,ct as w,d as T,et as E,f as D,g as O,h as k,i as A,it as j,j as M,l as N,lt as P,m as F,n as I,o as ve,ot as ye,p as L,q as be,r as xe,s as Se,st as Ce,t as we,u as Te,ut as Ee,v as R,x as De,y as Oe,z as ke}from"./dependency-manager-B9utPujC.js";import{t as Ae}from"./response-language-Dnr7IBrP.js";import{n as z,r as je,t as Me}from"./init-BkYF2xYP.js";import B from"chalk";import V from"path";import H from"fs";import U from"boxen";import{Command as Ne,Option as W}from"commander";import G from"inquirer";const K={AUTHENTICATION:`authentication`,VALIDATION:`validation`,NETWORK:`network`,API:`api`,FILE_SYSTEM:`file_system`,TASK:`task`,PERMISSION:`permission`,TIMEOUT:`timeout`,GENERIC:`generic`},q=[/\b[A-Za-z0-9_-]{20,}\b/g,/sk-[A-Za-z0-9]{32,}/g,/api[_-]?key[:\s=]+[^\s]+/gi,/bearer\s+[^\s]+/gi,/token[:\s=]+[^\s]+/gi,/\/Users\/[^/]+/g,/C:\\Users\\[^\\]+/g,/\/home\/[^/]+/g,/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g,/https?:\/\/[^:]+:[^@]+@/g];function J(e){if(!e||typeof e!=`string`)return e;let t=e;for(let e of q)t=t.replace(e,`***REDACTED***`);return t}function Pe(e){if(!e)return K.GENERIC;let t=(e.message||``).toLowerCase(),n=(e.code||``).toLowerCase();return t.includes(`auth`)||t.includes(`unauthorized`)||t.includes(`forbidden`)||t.includes(`api key`)||t.includes(`token`)||n.includes(`auth`)?K.AUTHENTICATION:t.includes(`invalid`)||t.includes(`validation`)||t.includes(`required`)||t.includes(`must be`)||n.includes(`validation`)?K.VALIDATION:t.includes(`network`)||t.includes(`connection`)||t.includes(`econnrefused`)||t.includes(`enotfound`)||n.includes(`network`)||n.includes(`econnrefused`)||n.includes(`enotfound`)?K.NETWORK:t.includes(`timeout`)||t.includes(`timed out`)||n.includes(`timeout`)?K.TIMEOUT:t.includes(`api`)||t.includes(`rate limit`)||t.includes(`quota`)||n.includes(`api`)?K.API:t.includes(`enoent`)||t.includes(`eacces`)||t.includes(`file`)||t.includes(`directory`)||n.includes(`enoent`)||n.includes(`eacces`)?K.FILE_SYSTEM:t.includes(`permission`)||t.includes(`access denied`)||n.includes(`eperm`)?K.PERMISSION:t.includes(`task`)||t.includes(`subtask`)?K.TASK:K.GENERIC}function Fe(e,t,n){let r=[],i=(t.message||``).toLowerCase();switch(e){case K.AUTHENTICATION:i.includes(`api key`)?(r.push(`Check that your API key is correctly set in the .env file`),r.push(`Verify the API key has not expired or been revoked`)):i.includes(`token`)?(r.push(`Your authentication token may have expired`),r.push(`Check the provider key in your .env file`)):(r.push(`Verify your credentials are correctly configured`),r.push(`Check that the provider key is set in your .env file`));break;case K.VALIDATION:i.includes(`task id`)||i.includes(`invalid id`)?(r.push(`Task IDs should be numbers (e.g., 1, 2, 3)`),r.push(`Subtask IDs use dot notation (e.g., 1.1, 2.3)`)):(r.push(`Check that all required parameters are provided`),r.push(`Verify parameter values match expected formats`));break;case K.NETWORK:i.includes(`econnrefused`)?(r.push(`Could not connect to the server`),r.push(`Check your internet connection`),r.push(`Verify the API endpoint URL is correct`)):i.includes(`enotfound`)?(r.push(`Could not resolve the server hostname`),r.push(`Check your internet connection`)):(r.push(`Check your network connection`),r.push(`Verify firewall settings are not blocking the request`));break;case K.TIMEOUT:r.push(`The operation took too long to complete`),r.push(`Try again with a simpler request`),r.push(`Check your network speed and stability`);break;case K.API:i.includes(`rate limit`)?(r.push(`You have exceeded the API rate limit`),r.push(`Wait a few minutes before trying again`)):i.includes(`quota`)?(r.push(`You have reached your API quota`),r.push(`Check your account usage and limits`)):(r.push(`The API returned an error`),r.push(`Try again in a few moments`));break;case K.FILE_SYSTEM:i.includes(`enoent`)?(r.push(`The specified file or directory does not exist`),r.push(`Check the file path and ensure it is correct`),n.includes(`tasks.json`)&&r.push(`Initialize the project with: tm init`)):i.includes(`eacces`)?(r.push(`Permission denied to access the file`),r.push(`Check file permissions or run with appropriate privileges`)):r.push(`Check that the file or directory exists and is accessible`);break;case K.PERMISSION:r.push(`You do not have permission to perform this operation`),r.push(`Check file/directory permissions`),r.push(`You may need elevated privileges (sudo)`);break;case K.TASK:i.includes(`not found`)?(r.push(`The specified task does not exist`),r.push(`Use: tm list to see all available tasks`)):i.includes(`dependency`)||i.includes(`circular`)?(r.push(`Task dependencies form a circular reference`),r.push(`Use: tm validate-dependencies to identify issues`)):(r.push(`Check that the task ID is correct`),r.push(`Use: tm show <id> to view task details`));break;default:r.push(`Check the error message for specific details`),n&&r.push(`Operation failed while: ${n}`)}return r.slice(0,2)}function Ie(e,t={}){let{context:n=``,debug:r=!1,command:i=``}=t;typeof e==`string`&&(e=Error(e)),(!e||typeof e!=`object`)&&(e=Error(`An unknown error occurred`));let a=J(e.message||`Unknown error`),o=Pe(e),s=Fe(o,e,n);return{type:o,message:a,context:n||`Unknown operation`,hints:s,command:i||null,code:e.code||null,stack:r?J(e.stack):null}}function Y(e,t={}){let n=Ie(e,t),r=B.red.bold(`✗ Error
2
2
 
3
- `);i+=t.text(r.message)+`
3
+ `);r+=h.text(n.message)+`
4
4
 
5
- `,r.context&&r.context!==`Unknown operation`&&(i+=t.muted(`Context: `)+t.text(r.context)+`
5
+ `,n.context&&n.context!==`Unknown operation`&&(r+=h.muted(`Context: `)+h.text(n.context)+`
6
6
 
7
- `),r.command&&(i+=t.muted(`Command: `)+B.cyan(r.command)+`
7
+ `),n.command&&(r+=h.muted(`Command: `)+B.cyan(n.command)+`
8
8
 
9
- `),r.hints&&r.hints.length>0&&(i+=B.yellow.bold(`Suggestions:
10
- `),r.hints.forEach((e,t)=>{i+=B.yellow(` ${t+1}. ${e}\n`)})),r.code&&(i+=`
11
- `+t.muted(`Error Code: ${r.code}`)),console.log(`
12
- `+U(i.trim(),{padding:{top:1,bottom:1,left:2,right:2},borderStyle:`round`,borderColor:`red`})+`
13
- `),n.debug&&r.stack&&(console.log(t.muted(`Stack Trace:`)),console.log(B.dim(r.stack)),console.log())}function Le(e,n=`Info`){let r=t.brand.bold(`ℹ ${n}\n\n`);r+=t.text(e),console.log(`
14
- `+U(r.trim(),{padding:{top:1,bottom:1,left:2,right:2},borderStyle:`round`,borderColor:h})+`
15
- `)}var Re=class{#e;#t;constructor(e,t){this.#e=Object.freeze({...e}),this.#t=t}getProjectRoot(){return this.#e.projectRoot}getTaskGraphDir(){return this.#e.taskGraphDir}getTasksPath(){return this.#e.tasksPath}getPrdPath(){return this.#e.prdPath}getComplexityReportPath(){if(this.#e.complexityReportPath)return this.#e.complexityReportPath;let e=this.getCurrentTag()===`master`?m:m.replace(`.json`,`_${this.getCurrentTag()}.json`);return H.join(this.#e.projectRoot,e)}getConfigPath(){return this.#e.configPath}getStatePath(){return this.#e.statePath}getAllPaths(){return this.#e}getCurrentTag(){if(this.#t)return this.#t;try{if(V.existsSync(this.#e.statePath)){let e=V.readFileSync(this.#e.statePath,`utf8`),t=JSON.parse(e);if(t&&t.currentTag)return t.currentTag}}catch{}try{if(V.existsSync(this.#e.configPath)){let e=V.readFileSync(this.#e.configPath,`utf8`),t=JSON.parse(e);if(t&&t.global&&t.global.defaultTag)return t.global.defaultTag}}catch{}return`master`}};function X(t={}){let n=(e,t,n=[],r=null,i=!1)=>{if(typeof t==`string`){let n=H.isAbsolute(t)?t:H.resolve(r||process.cwd(),t);if(i){let t=H.dirname(n);if(!V.existsSync(t))try{V.mkdirSync(t,{recursive:!0})}catch(n){throw Error(`Could not create directory for ${e}: ${t}. Error: ${n.message}`)}}else if(!V.existsSync(n))throw Error(`${e} override path does not exist: ${n}`);return n}if(t===!0){for(let e of n){let t=H.isAbsolute(e)?e:H.join(r||process.cwd(),e);if(V.existsSync(t))return t}throw Error(`Required ${e} not found. Searched: ${n.join(`, `)}`)}for(let e of n){let t=H.isAbsolute(e)?e:H.join(r||process.cwd(),e);if(V.existsSync(t))return t}return null},o={};if(t.projectRoot){let n=H.resolve(t.projectRoot);if(!V.existsSync(n))throw Error(`Project root override path does not exist: ${n}`);if(!V.existsSync(H.join(n,e)))throw Error(`Project root override is not a valid taskgraph project: ${n}`);o.projectRoot=n}else o.projectRoot=i();return`taskGraphDir`in t?o.taskGraphDir=n(`taskgraph directory`,t.taskGraphDir,[e],o.projectRoot):o.taskGraphDir=n(`taskgraph directory`,!1,[e],o.projectRoot),o.configPath=H.join(o.projectRoot,u),o.statePath=H.join(o.taskGraphDir||H.join(o.projectRoot,e),`state.json`),o.tasksPath=H.join(o.projectRoot,r),`configPath`in t&&(o.configPath=n(`config file`,t.configPath,[u],o.projectRoot)),`statePath`in t&&(o.statePath=n(`state file`,t.statePath,[`state.json`],o.taskGraphDir)),`tasksPath`in t&&(o.tasksPath=n(`tasks file`,t.tasksPath,[r],o.projectRoot)),`prdPath`in t&&(o.prdPath=n(`PRD file`,t.prdPath,[H.join(l,`PRD.md`),H.join(l,`prd.md`),H.join(l,`PRD.txt`),H.join(l,`prd.txt`)],o.projectRoot)),`complexityReportPath`in t&&(o.complexityReportPath=n(`complexity report`,t.complexityReportPath,[H.join(a,`task-complexity-report.json`),H.join(a,`complexity-report.json`)],o.projectRoot,!0)),new Re(o,t.tag)}function Z(e){e.on(`option:unknown`,function(e){let t=this._name||`unknown`;Y(Error(`Unknown option '${e}'`),{context:`Running command: ${t}`,command:`taskgraph ${t}`,debug:d()}),process.exit(1)}),e.command(`help`).description(`Show help information`).action(()=>{e.help()}),e.configureHelp({helpWidth:120,sortSubcommands:!1}),e.command(`parse-prd`).description(`Parse a PRD file and generate tasks`).argument(`[file]`,`Path to the PRD file`).option(`-i, --input <file>`,`Path to the PRD file (alternative to positional argument)`).option(`-o, --output <file>`,`Output file path`).option(`-n, --num-tasks <number>`,`Number of tasks to generate`,s()).option(`-f, --force`,`Skip confirmation when overwriting existing tasks`).option(`--append`,`Append new tasks to existing tasks.json instead of overwriting`).option(`-r, --research`,`Use Claude Code web research for research-backed task generation, providing more comprehensive and accurate task breakdown`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async(e,n)=>{let i=n.input||e,a;try{let e={prdPath:i||!0,tag:n.tag};n.output&&(e.tasksPath=n.output),a=X(e)}catch(e){Y(e,{context:`Initializing TaskGraph for PRD parsing`,command:`taskgraph parse-prd`,debug:d()}),Le(`${B.cyan(`Usage:`)}\n taskgraph parse-prd <prd-file.txt> [options]\n\n${B.cyan(`Options:`)}\n -i, --input <file> Path to the PRD file\n -o, --output <file> Output file path\n -n, --num-tasks <number> Number of tasks to generate\n -f, --force Skip confirmation\n --append Append to existing tasks\n -r, --research Use Claude Code web research\n\n${B.cyan(`Examples:`)}\n taskgraph parse-prd requirements.txt --num-tasks 15\n taskgraph parse-prd --input=requirements.txt\n taskgraph parse-prd requirements.txt --research`,`Parse PRD Help`),process.exit(1)}let o=parseInt(n.numTasks,10),s=n.force||!1,l=n.append||!1,u=n.research||!1,f=s,p=l,m=a.getCurrentTag();await T(m);async function h(){let e=!1,t=a.getTasksPath();if(V.existsSync(t))try{let n=V.readFileSync(t,`utf8`),r=JSON.parse(n);r[m]&&Array.isArray(r[m].tasks)&&r[m].tasks.length>0&&(e=!0)}catch{e=!1}if(e&&!f&&!p){if(!await ve(t))return c(`info`,`Operation cancelled.`),!1;f=!0}return!0}try{if(!await h())return;console.log(t.brand(`Parsing PRD file: ${a.getPrdPath()}`)),console.log(t.brand(`Generating ${o} tasks...`)),l&&console.log(t.brand(`Appending to existing tasks...`)),u&&console.log(t.brand(`Using Claude Code web research for research-backed task generation`));let e=a.getTasksPath()||H.join(a.getProjectRoot(),r);await le(a.getPrdPath(),e,o,{append:p,force:f,research:u,projectRoot:a.getProjectRoot(),tag:m})}catch(e){console.error(B.red(`Error parsing PRD: ${e.message}`)),process.exit(1)}}),e.command(`update`).description(`Update multiple tasks with ID >= "from" based on new information or implementation changes`).option(`-f, --file <file>`,`Path to the tasks file`,r).option(`--from <id>`,`Task ID to start updating from (tasks with ID >= this value will be updated)`,`1`).option(`-p, --prompt <text>`,`Prompt explaining the changes or new context (required)`).option(`-r, --research`,`Use Claude Code web research for research-backed task updates`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let n=X({tasksPath:e.file||!0,tag:e.tag}),r=parseInt(e.from,10),i=e.prompt,a=e.research||!1,o=n.getTasksPath(),s=n.getCurrentTag();await T(s),(process.argv.includes(`--id`)||process.argv.some(e=>e.startsWith(`--id=`)))&&(console.error(B.red(`Error: The update command uses --from=<id>, not --id=<id>`)),console.log(B.yellow(`
16
- To update multiple tasks:`)),console.log(` taskgraph update --from=${r} --prompt="Your prompt here"`),console.log(B.yellow(`
17
- To update a single specific task, use the update-task command instead:`)),console.log(` taskgraph update-task --id=<id> --prompt="Your prompt here"`),process.exit(1)),i||(console.error(B.red(`Error: --prompt parameter is required. Please provide information about the changes.`)),process.exit(1)),console.log(t.brand(`Updating tasks from ID >= ${r} with prompt: "${i}"`)),console.log(t.brand(`Tasks file: ${o}`)),a&&console.log(t.brand(`Using Claude Code web research for research-backed task updates`)),await De(n.getTasksPath(),r,i,a,{projectRoot:n.getProjectRoot(),tag:s})}),e.command(`update-task`).description(`Update a single specific task by ID with new information`).argument(`[id]`,`Task ID to update (e.g., 1, 1.1, TAS-123)`).argument(`[prompt...]`,`Update prompt - multiple words, no quotes needed`).option(`-f, --file <file>`,`Path to the tasks file`,r).option(`-i, --id <id>`,`Task ID to update (fallback if not using positional)`).option(`-p, --prompt <text>`,`Prompt (fallback if not using positional)`).option(`-r, --research`,`Use Claude Code web research for research-backed task updates`).option(`--append`,`Append timestamped information to task details instead of full update`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async(e,n,i)=>{try{let a=X({tasksPath:i.file||!0,tag:i.tag}),o=a.getTasksPath(),s=a.getCurrentTag();await T(s);let c=e||i.id,l=n.length>0?n.join(` `):i.prompt;c||(console.error(B.red(`Error: Task ID is required`)),console.log(B.yellow(`Usage examples:
9
+ `),n.hints&&n.hints.length>0&&(r+=B.yellow.bold(`Suggestions:
10
+ `),n.hints.forEach((e,t)=>{r+=B.yellow(` ${t+1}. ${e}\n`)})),n.code&&(r+=`
11
+ `+h.muted(`Error Code: ${n.code}`)),console.log(`
12
+ `+U(r.trim(),{padding:{top:1,bottom:1,left:2,right:2},borderStyle:`round`,borderColor:`red`})+`
13
+ `),t.debug&&n.stack&&(console.log(h.muted(`Stack Trace:`)),console.log(B.dim(n.stack)),console.log())}function Le(e,t=`Info`){let n=h.brand.bold(`ℹ ${t}\n\n`);n+=h.text(e),console.log(`
14
+ `+U(n.trim(),{padding:{top:1,bottom:1,left:2,right:2},borderStyle:`round`,borderColor:c})+`
15
+ `)}var Re=class{#e;#t;constructor(e,t){this.#e=Object.freeze({...e}),this.#t=t}getProjectRoot(){return this.#e.projectRoot}getTaskGraphDir(){return this.#e.taskGraphDir}getTasksPath(){return this.#e.tasksPath}getPrdPath(){return this.#e.prdPath}getComplexityReportPath(){if(this.#e.complexityReportPath)return this.#e.complexityReportPath;let e=this.getCurrentTag()===`master`?o:o.replace(`.json`,`_${this.getCurrentTag()}.json`);return V.join(this.#e.projectRoot,e)}getConfigPath(){return this.#e.configPath}getStatePath(){return this.#e.statePath}getAllPaths(){return this.#e}getCurrentTag(){if(this.#t)return this.#t;try{if(H.existsSync(this.#e.statePath)){let e=H.readFileSync(this.#e.statePath,`utf8`),t=JSON.parse(e);if(t&&t.currentTag)return t.currentTag}}catch{}try{if(H.existsSync(this.#e.configPath)){let e=H.readFileSync(this.#e.configPath,`utf8`),t=JSON.parse(e);if(t&&t.global&&t.global.defaultTag)return t.global.defaultTag}}catch{}return`master`}};function X(r={}){let o=(e,t,n=[],r=null,i=!1)=>{if(typeof t==`string`){let n=V.isAbsolute(t)?t:V.resolve(r||process.cwd(),t);if(i){let t=V.dirname(n);if(!H.existsSync(t))try{H.mkdirSync(t,{recursive:!0})}catch(n){throw Error(`Could not create directory for ${e}: ${t}. Error: ${n.message}`)}}else if(!H.existsSync(n))throw Error(`${e} override path does not exist: ${n}`);return n}if(t===!0){for(let e of n){let t=V.isAbsolute(e)?e:V.join(r||process.cwd(),e);if(H.existsSync(t))return t}throw Error(`Required ${e} not found. Searched: ${n.join(`, `)}`)}for(let e of n){let t=V.isAbsolute(e)?e:V.join(r||process.cwd(),e);if(H.existsSync(t))return t}return null},s={};if(r.projectRoot){let e=V.resolve(r.projectRoot);if(!H.existsSync(e))throw Error(`Project root override path does not exist: ${e}`);if(!H.existsSync(V.join(e,a)))throw Error(`Project root override is not a valid taskgraph project: ${e}`);s.projectRoot=e}else s.projectRoot=n();return`taskGraphDir`in r?s.taskGraphDir=o(`taskgraph directory`,r.taskGraphDir,[a],s.projectRoot):s.taskGraphDir=o(`taskgraph directory`,!1,[a],s.projectRoot),s.configPath=V.join(s.projectRoot,t),s.statePath=V.join(s.taskGraphDir||V.join(s.projectRoot,a),`state.json`),s.tasksPath=V.join(s.projectRoot,i),`configPath`in r&&(s.configPath=o(`config file`,r.configPath,[t],s.projectRoot)),`statePath`in r&&(s.statePath=o(`state file`,r.statePath,[`state.json`],s.taskGraphDir)),`tasksPath`in r&&(s.tasksPath=o(`tasks file`,r.tasksPath,[i],s.projectRoot)),`prdPath`in r&&(s.prdPath=o(`PRD file`,r.prdPath,[V.join(u,`PRD.md`),V.join(u,`prd.md`),V.join(u,`PRD.txt`),V.join(u,`prd.txt`)],s.projectRoot)),`complexityReportPath`in r&&(s.complexityReportPath=o(`complexity report`,r.complexityReportPath,[V.join(e,`task-complexity-report.json`),V.join(e,`complexity-report.json`)],s.projectRoot,!0)),new Re(s,r.tag)}function Z(e){e.on(`option:unknown`,function(e){let t=this._name||`unknown`;Y(Error(`Unknown option '${e}'`),{context:`Running command: ${t}`,command:`taskgraph ${t}`,debug:f()}),process.exit(1)}),e.command(`help`).description(`Show help information`).action(()=>{e.help()}),e.configureHelp({helpWidth:120,sortSubcommands:!1}),e.command(`parse-prd`).description(`Parse a PRD file and generate tasks`).argument(`[file]`,`Path to the PRD file`).option(`-i, --input <file>`,`Path to the PRD file (alternative to positional argument)`).option(`-o, --output <file>`,`Output file path`).option(`-n, --num-tasks <number>`,`Number of tasks to generate`,p()).option(`-f, --force`,`Skip confirmation when overwriting existing tasks`).option(`--append`,`Append new tasks to existing tasks.json instead of overwriting`).option(`-r, --research`,`Use Claude Code web research for research-backed task generation, providing more comprehensive and accurate task breakdown`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async(e,t)=>{let n=t.input||e,r;try{let e={prdPath:n||!0,tag:t.tag};t.output&&(e.tasksPath=t.output),r=X(e)}catch(e){Y(e,{context:`Initializing TaskGraph for PRD parsing`,command:`taskgraph parse-prd`,debug:f()}),Le(`${B.cyan(`Usage:`)}\n taskgraph parse-prd <prd-file.txt> [options]\n\n${B.cyan(`Options:`)}\n -i, --input <file> Path to the PRD file\n -o, --output <file> Output file path\n -n, --num-tasks <number> Number of tasks to generate\n -f, --force Skip confirmation\n --append Append to existing tasks\n -r, --research Use Claude Code web research\n\n${B.cyan(`Examples:`)}\n taskgraph parse-prd requirements.txt --num-tasks 15\n taskgraph parse-prd --input=requirements.txt\n taskgraph parse-prd requirements.txt --research`,`Parse PRD Help`),process.exit(1)}let a=parseInt(t.numTasks,10),o=t.force||!1,s=t.append||!1,c=t.research||!1,l=o,u=s,p=r.getCurrentTag();await T(p);async function m(){let e=!1,t=r.getTasksPath();if(H.existsSync(t))try{let n=H.readFileSync(t,`utf8`),r=JSON.parse(n);r[p]&&Array.isArray(r[p].tasks)&&r[p].tasks.length>0&&(e=!0)}catch{e=!1}if(e&&!l&&!u){if(!await ve(t))return d(`info`,`Operation cancelled.`),!1;l=!0}return!0}try{if(!await m())return;console.log(h.brand(`Parsing PRD file: ${r.getPrdPath()}`)),console.log(h.brand(`Generating ${a} tasks...`)),s&&console.log(h.brand(`Appending to existing tasks...`)),c&&console.log(h.brand(`Using Claude Code web research for research-backed task generation`));let e=r.getTasksPath()||V.join(r.getProjectRoot(),i);await le(r.getPrdPath(),e,a,{append:u,force:l,research:c,projectRoot:r.getProjectRoot(),tag:p})}catch(e){console.error(B.red(`Error parsing PRD: ${e.message}`)),process.exit(1)}}),e.command(`update`).description(`Update multiple tasks with ID >= "from" based on new information or implementation changes`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`--from <id>`,`Task ID to start updating from (tasks with ID >= this value will be updated)`,`1`).option(`-p, --prompt <text>`,`Prompt explaining the changes or new context (required)`).option(`-r, --research`,`Use Claude Code web research for research-backed task updates`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t=X({tasksPath:e.file||!0,tag:e.tag}),n=parseInt(e.from,10),r=e.prompt,i=e.research||!1,a=t.getTasksPath(),o=t.getCurrentTag();await T(o),(process.argv.includes(`--id`)||process.argv.some(e=>e.startsWith(`--id=`)))&&(console.error(B.red(`Error: The update command uses --from=<id>, not --id=<id>`)),console.log(B.yellow(`
16
+ To update multiple tasks:`)),console.log(` taskgraph update --from=${n} --prompt="Your prompt here"`),console.log(B.yellow(`
17
+ To update a single specific task, use the update-task command instead:`)),console.log(` taskgraph update-task --id=<id> --prompt="Your prompt here"`),process.exit(1)),r||(console.error(B.red(`Error: --prompt parameter is required. Please provide information about the changes.`)),process.exit(1)),console.log(h.brand(`Updating tasks from ID >= ${n} with prompt: "${r}"`)),console.log(h.brand(`Tasks file: ${a}`)),i&&console.log(h.brand(`Using Claude Code web research for research-backed task updates`)),await De(t.getTasksPath(),n,r,i,{projectRoot:t.getProjectRoot(),tag:o})}),e.command(`update-task`).description(`Update a single specific task by ID with new information`).argument(`[id]`,`Task ID to update (e.g., 1, 1.1, TAS-123)`).argument(`[prompt...]`,`Update prompt - multiple words, no quotes needed`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`-i, --id <id>`,`Task ID to update (fallback if not using positional)`).option(`-p, --prompt <text>`,`Prompt (fallback if not using positional)`).option(`-r, --research`,`Use Claude Code web research for research-backed task updates`).option(`--append`,`Append timestamped information to task details instead of full update`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async(e,t,n)=>{try{let r=X({tasksPath:n.file||!0,tag:n.tag}),a=r.getTasksPath(),o=r.getCurrentTag();await T(o);let s=e||n.id,c=t.length>0?t.join(` `):n.prompt;s||(console.error(B.red(`Error: Task ID is required`)),console.log(B.yellow(`Usage examples:
18
18
  tm update-task 1 Added implementation details
19
19
  tm update-task TAS-123 Fixed the auth bug
20
- tm update-task --id=23 --prompt="Update with new information"`)),process.exit(1)),/^\d+$/.test(c)||/^[a-z]+-\d+$/i.test(c)||(console.error(B.red(`Error: Invalid task ID: ${c}. Task ID must be a positive integer or in the form "ham-123".`)),console.log(B.yellow(`Usage examples:
20
+ tm update-task --id=23 --prompt="Update with new information"`)),process.exit(1)),/^\d+$/.test(s)||(console.error(B.red(`Error: Invalid task ID: ${s}. Task ID must be a positive integer.`)),console.log(B.yellow(`Usage examples:
21
21
  tm update-task 1 Added implementation details
22
- tm update-task TAS-123 Fixed the auth bug`)),process.exit(1)),l||(console.error(B.red(`Error: Prompt is required. Please provide information about the changes.`)),console.log(B.yellow(`Usage examples:
22
+ tm update-task 7 Fixed the auth bug`)),process.exit(1)),c||(console.error(B.red(`Error: Prompt is required. Please provide information about the changes.`)),console.log(B.yellow(`Usage examples:
23
23
  tm update-task 1 Added implementation details
24
- tm update-task 23 "Update with new information"`)),process.exit(1));let u=i.research||!1;V.existsSync(o)||(console.error(B.red(`Error: Tasks file not found at path: ${o}`)),o===r?console.log(B.yellow(`Hint: Run taskgraph init or taskgraph parse-prd to create tasks.json first`)):console.log(B.yellow(`Hint: Check if the file path is correct: ${o}`)),process.exit(1)),console.log(t.brand(`Updating task ${c} with prompt: "${l}"`)),console.log(t.brand(`Tasks file: ${o}`)),u&&console.log(t.brand(`Using Claude Code web research for this update`));let d=i.append||!1;await fe(a.getTasksPath(),c,l,u,{projectRoot:a.getProjectRoot(),tag:s},`text`,d)||console.log(B.yellow(`
24
+ tm update-task 23 "Update with new information"`)),process.exit(1));let l=n.research||!1;H.existsSync(a)||(console.error(B.red(`Error: Tasks file not found at path: ${a}`)),a===i?console.log(B.yellow(`Hint: Run taskgraph init or taskgraph parse-prd to create tasks.json first`)):console.log(B.yellow(`Hint: Check if the file path is correct: ${a}`)),process.exit(1)),console.log(h.brand(`Updating task ${s} with prompt: "${c}"`)),console.log(h.brand(`Tasks file: ${a}`)),l&&console.log(h.brand(`Using Claude Code web research for this update`));let u=n.append||!1;await fe(r.getTasksPath(),s,c,l,{projectRoot:r.getProjectRoot(),tag:o},`text`,u)||console.log(B.yellow(`
25
25
  Task update was not completed. Review the messages above for details.`))}catch(e){console.error(B.red(`Error: ${e.message}`)),e.message.includes(`task`)&&e.message.includes(`not found`)?(console.log(B.yellow(`
26
26
  To fix this issue:`)),console.log(` 1. Run taskgraph list to see all available task IDs`),console.log(` 2. Use a valid task ID with the --id parameter`)):e.message.includes(`API key`)&&console.log(B.yellow(`
27
- This error is related to API keys. Check your environment variables.`)),d()&&console.error(e),process.exit(1)}}),e.command(`update-subtask`).description(`Update a subtask by appending additional timestamped information`).option(`-f, --file <file>`,`Path to the tasks file`,r).option(`-i, --id <id>`,`Subtask ID to update (required)`).option(`-p, --prompt <text>`,`Prompt explaining what information to add (required)`).option(`-r, --research`,`Use Claude Code web research for research-backed updates`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{try{let n=X({tasksPath:e.file||!0,tag:e.tag}),i=n.getTasksPath(),a=n.getCurrentTag();await T(a),e.id||(console.error(B.red(`Error: --id parameter is required`)),console.log(B.yellow(`Usage example: taskgraph update-subtask --id=5.2 --prompt="Add more details about the API endpoint"`)),process.exit(1));let o=e.id;e.prompt||(console.error(B.red(`Error: --prompt parameter is required. Please provide information to add to the subtask.`)),console.log(B.yellow(`Usage example: taskgraph update-subtask --id=5.2 --prompt="Add more details about the API endpoint"`)),process.exit(1));let s=e.prompt,c=e.research||!1;V.existsSync(i)||(console.error(B.red(`Error: Tasks file not found at path: ${i}`)),i===r?console.log(B.yellow(`Hint: Run taskgraph init or taskgraph parse-prd to create tasks.json first`)):console.log(B.yellow(`Hint: Check if the file path is correct: ${i}`)),process.exit(1)),console.log(t.brand(`Updating subtask ${o} with prompt: "${s}"`)),console.log(t.brand(`Tasks file: ${i}`)),c&&console.log(t.brand(`Using Claude Code web research for this update`)),await ne(n.getTasksPath(),o,s,c,{projectRoot:n.getProjectRoot(),tag:a})||console.log(B.yellow(`
27
+ This error is related to API keys. Check your environment variables.`)),f()&&console.error(e),process.exit(1)}}),e.command(`update-subtask`).description(`Update a subtask by appending additional timestamped information`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`-i, --id <id>`,`Subtask ID to update (required)`).option(`-p, --prompt <text>`,`Prompt explaining what information to add (required)`).option(`-r, --research`,`Use Claude Code web research for research-backed updates`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{try{let t=X({tasksPath:e.file||!0,tag:e.tag}),n=t.getTasksPath(),r=t.getCurrentTag();await T(r),e.id||(console.error(B.red(`Error: --id parameter is required`)),console.log(B.yellow(`Usage example: taskgraph update-subtask --id=5.2 --prompt="Add more details about the API endpoint"`)),process.exit(1));let a=e.id;e.prompt||(console.error(B.red(`Error: --prompt parameter is required. Please provide information to add to the subtask.`)),console.log(B.yellow(`Usage example: taskgraph update-subtask --id=5.2 --prompt="Add more details about the API endpoint"`)),process.exit(1));let o=e.prompt,s=e.research||!1;H.existsSync(n)||(console.error(B.red(`Error: Tasks file not found at path: ${n}`)),n===i?console.log(B.yellow(`Hint: Run taskgraph init or taskgraph parse-prd to create tasks.json first`)):console.log(B.yellow(`Hint: Check if the file path is correct: ${n}`)),process.exit(1)),console.log(h.brand(`Updating subtask ${a} with prompt: "${o}"`)),console.log(h.brand(`Tasks file: ${n}`)),s&&console.log(h.brand(`Using Claude Code web research for this update`)),await ne(t.getTasksPath(),a,o,s,{projectRoot:t.getProjectRoot(),tag:r})||console.log(B.yellow(`
28
28
  Subtask update was not completed. Review the messages above for details.`))}catch(e){console.error(B.red(`Error: ${e.message}`)),e.message.includes(`subtask`)&&e.message.includes(`not found`)?(console.log(B.yellow(`
29
29
  To fix this issue:`)),console.log(` 1. Run taskgraph list --with-subtasks to see all available subtask IDs`),console.log(` 2. Use a valid subtask ID with the --id parameter in format "parentId.subtaskId"`)):e.message.includes(`API key`)&&console.log(B.yellow(`
30
- This error is related to API keys. Check your environment variables.`)),d()&&console.error(e),process.exit(1)}}),e.command(`scope-up`).description(`Increase task complexity with AI assistance`).option(`-f, --file <file>`,`Path to the tasks file`,r).option(`-i, --id <ids>`,`Comma-separated task/subtask IDs to scope up (required)`).option(`-s, --strength <level>`,`Complexity increase strength: light, regular, heavy`,`regular`).option(`-p, --prompt <text>`,`Custom instructions for targeted scope adjustments`).option(`-r, --research`,`Use research AI for more informed adjustments`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{try{let n=X({tasksPath:e.file||!0,tag:e.tag}),r=n.getTasksPath(),i=n.getCurrentTag();await T(i),e.id||(console.error(B.red(`Error: --id parameter is required`)),console.log(B.yellow(`Usage example: taskgraph scope-up --id=1,2,3 --strength=regular`)),process.exit(1));let a=e.id.split(`,`).map(e=>{let t=parseInt(e.trim(),10);return(Number.isNaN(t)||t<=0)&&(console.error(B.red(`Error: Invalid task ID: ${e.trim()}`)),process.exit(1)),t});y(e.strength)||(console.error(B.red(`Error: Invalid strength level: ${e.strength}. Must be one of: light, regular, heavy`)),process.exit(1)),V.existsSync(r)||(console.error(B.red(`Error: Tasks file not found at path: ${r}`)),process.exit(1)),console.log(t.brand(`Scoping up ${a.length} task(s): ${a.join(`, `)}`)),console.log(t.brand(`Strength level: ${e.strength}`)),e.prompt&&console.log(t.brand(`Custom instructions: ${e.prompt}`));let o={projectRoot:n.getProjectRoot(),tag:i,commandName:`scope-up`,outputType:`cli`,research:e.research||!1},s=await re(r,a,e.strength,e.prompt||null,o,`text`);console.log(B.green(`✅ Successfully scoped up ${s.updatedTasks.length} task(s)`))}catch(e){console.error(B.red(`Error: ${e.message}`)),e.message.includes(`not found`)&&(console.log(B.yellow(`
31
- To fix this issue:`)),console.log(` 1. Run taskgraph list to see all available task IDs`),console.log(` 2. Use valid task IDs with the --id parameter`)),d()&&console.error(e),process.exit(1)}}),e.command(`scope-down`).description(`Decrease task complexity with AI assistance`).option(`-f, --file <file>`,`Path to the tasks file`,r).option(`-i, --id <ids>`,`Comma-separated task/subtask IDs to scope down (required)`).option(`-s, --strength <level>`,`Complexity decrease strength: light, regular, heavy`,`regular`).option(`-p, --prompt <text>`,`Custom instructions for targeted scope adjustments`).option(`-r, --research`,`Use research AI for more informed adjustments`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{try{let n=X({tasksPath:e.file||!0,tag:e.tag}),r=n.getTasksPath(),i=n.getCurrentTag();await T(i),e.id||(console.error(B.red(`Error: --id parameter is required`)),console.log(B.yellow(`Usage example: taskgraph scope-down --id=1,2,3 --strength=regular`)),process.exit(1));let a=e.id.split(`,`).map(e=>{let t=parseInt(e.trim(),10);return(Number.isNaN(t)||t<=0)&&(console.error(B.red(`Error: Invalid task ID: ${e.trim()}`)),process.exit(1)),t});y(e.strength)||(console.error(B.red(`Error: Invalid strength level: ${e.strength}. Must be one of: light, regular, heavy`)),process.exit(1)),V.existsSync(r)||(console.error(B.red(`Error: Tasks file not found at path: ${r}`)),process.exit(1)),console.log(t.brand(`Scoping down ${a.length} task(s): ${a.join(`, `)}`)),console.log(t.brand(`Strength level: ${e.strength}`)),e.prompt&&console.log(t.brand(`Custom instructions: ${e.prompt}`));let o={projectRoot:n.getProjectRoot(),tag:i,commandName:`scope-down`,outputType:`cli`,research:e.research||!1},s=await _(r,a,e.strength,e.prompt||null,o,`text`);console.log(B.green(`✅ Successfully scoped down ${s.updatedTasks.length} task(s)`))}catch(e){console.error(B.red(`Error: ${e.message}`)),e.message.includes(`not found`)&&(console.log(B.yellow(`
32
- To fix this issue:`)),console.log(` 1. Run taskgraph list to see all available task IDs`),console.log(` 2. Use valid task IDs with the --id parameter`)),d()&&console.error(e),process.exit(1)}}),he(e),e.command(`expand`).description(`Expand a task into subtasks using AI`).option(`-i, --id <id>`,`ID of the task to expand`).option(`-a, --all`,`Expand all pending tasks based on complexity analysis`).option(`-n, --num <number>`,`Number of subtasks to generate (uses complexity analysis by default if available)`).option(`-r, --research`,`Enable research-backed generation (web research via Claude Code)`,!1).option(`-p, --prompt <text>`,`Additional context for subtask generation`).option(`-f, --force`,`Force expansion even if subtasks exist`,!1).option(`--file <file>`,`Path to the tasks file (relative to project root)`,r).option(`-cr, --complexity-report <file>`,`Path to the complexity report file (use this to specify the complexity report, not --file)`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async n=>{let r={tasksPath:n.file||!0,tag:n.tag};n.complexityReport&&(r.complexityReportPath=n.complexityReport);let i=X(r),a=i.getCurrentTag();if(await T(a),n.all){console.log(t.brand(`Expanding all pending tasks...`));try{await de(i.getTasksPath(),n.num,n.research,n.prompt,n.force,{projectRoot:i.getProjectRoot(),tag:a,complexityReportPath:i.getComplexityReportPath()})}catch(e){console.error(B.red(`Error expanding all tasks: ${e.message}`)),process.exit(1)}}else if(n.id){n.id||(console.error(B.red(`Error: Task ID is required unless using --all.`)),process.exit(1)),console.log(t.brand(`Expanding task ${n.id}...`));try{await ke(i.getTasksPath(),n.id,n.num,n.research,n.prompt,{projectRoot:i.getProjectRoot(),tag:a,complexityReportPath:i.getComplexityReportPath()},n.force)}catch(e){console.error(B.red(`Error expanding task ${n.id}: ${e.message}`)),process.exit(1)}}else console.error(B.red(`Error: You must specify either a task ID (--id) or --all.`)),e.help()}),e.command(`analyze-complexity`).description(`Analyze tasks and generate expansion recommendations${B.reset(``)}`).option(`-o, --output <file>`,`Output file path for the report`).option(`-m, --model <model>`,`LLM model to use for analysis (defaults to configured model)`).option(`-t, --threshold <number>`,`Minimum complexity score to recommend expansion (1-10)`,`5`).option(`-f, --file <file>`,`Path to the tasks file`,r).option(`-r, --research`,`Use configured research model for research-backed complexity analysis`).option(`-i, --id <ids>`,`Comma-separated list of specific task IDs to analyze (e.g., "1,3,5")`).option(`--from <id>`,`Starting task ID in a range to analyze`).option(`--to <id>`,`Ending task ID in a range to analyze`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let n={tasksPath:e.file||!0,tag:e.tag};e.output&&(n.complexityReportPath=e.output);let r=X(n);e.model,parseFloat(e.threshold);let i=e.research||!1,a=r.getCurrentTag();await T(a);let o=r.getComplexityReportPath();if(console.log(t.brand(`Analyzing task complexity from: ${r.getTasksPath()}`)),console.log(t.brand(`Output report will be saved to: ${o}`)),e.id)console.log(t.brand(`Analyzing specific task IDs: ${e.id}`));else if(e.from||e.to){let n=e.from?e.from:`first`,r=e.to?e.to:`last`;console.log(t.brand(`Analyzing tasks in range: ${n} to ${r}`))}i&&console.log(t.brand(`Using Claude Code web research for research-backed complexity analysis`)),await pe({...e,output:o,tag:a,projectRoot:r.getProjectRoot(),file:r.getTasksPath()})}),e.command(`research`).description(`Perform AI-powered research queries with project context`).argument(`[prompt]`,`Research prompt to investigate`).option(`--file <file>`,`Path to the tasks file`).option(`-i, --id <ids>`,`Comma-separated task/subtask IDs to include as context (e.g., "15,16.2")`).option(`-f, --files <paths>`,`Comma-separated file paths to include as context`).option(`-c, --context <text>`,`Additional custom context to include in the research prompt`).option(`-t, --tree`,`Include project file tree structure in the research context`).option(`-s, --save <file>`,`Save research results to the specified task/subtask(s)`).option(`-d, --detail <level>`,`Output detail level: low, medium, high`,`medium`).option(`--save-to <id>`,`Automatically save research results to specified task/subtask ID (e.g., "15" or "15.2")`).option(`--save-file`,`Save research results to .taskgraph/docs/research/ directory`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async(e,n)=>{let r=X({tasksPath:n.file||!0,tag:n.tag});(!e||typeof e!=`string`||e.trim().length===0)&&(console.error(B.red(`Error: Research prompt is required and cannot be empty`)),x(),process.exit(1));let i=[`low`,`medium`,`high`];n.detail&&!i.includes(n.detail.toLowerCase())&&(console.error(B.red(`Error: Detail level must be one of: ${i.join(`, `)}`)),process.exit(1));let a=[];if(n.id)try{a=n.id.split(`,`).map(e=>{let t=e.trim();if(!/^\d+(\.\d+)?$/.test(t))throw Error(`Invalid task ID format: "${t}". Expected format: "15" or "15.2"`);return t})}catch(e){console.error(B.red(`Error parsing task IDs: ${e.message}`)),process.exit(1)}let o=[];if(n.files)try{o=n.files.split(`,`).map(e=>{let t=e.trim();if(t.length===0)throw Error(`Empty file path provided`);return t})}catch(e){console.error(B.red(`Error parsing file paths: ${e.message}`)),process.exit(1)}if(n.saveTo){let e=n.saveTo.trim();e.length===0&&(console.error(B.red(`Error: Save-to ID cannot be empty`)),process.exit(1)),/^\d+(\.\d+)?$/.test(e)||(console.error(B.red(`Error: Save-to ID must be in format "15" for task or "15.2" for subtask`)),process.exit(1))}if(n.save){let e=n.save.trim();e.length===0&&(console.error(B.red(`Error: Save target cannot be empty`)),process.exit(1)),(e.includes(`..`)||e.startsWith(`/`))&&(console.error(B.red(`Error: Save path must be relative and cannot contain ".."`)),process.exit(1))}let s=r.getCurrentTag();if(await T(s),a.length>0)try{let e=p(r.getTasksPath(),r.getProjectRoot(),s);(!e||!e.tasks)&&(console.error(B.red(`Error: No valid tasks found in ${r.getTasksPath()} for tag '${s}'`)),process.exit(1))}catch(e){console.error(B.red(`Error reading tasks file: ${e.message}`)),process.exit(1)}if(o.length>0)for(let e of o){let t=H.isAbsolute(e)?e:H.join(r.getProjectRoot(),e);V.existsSync(t)||(console.error(B.red(`Error: File not found: ${e}`)),process.exit(1))}let c={prompt:e.trim(),taskIds:a,filePaths:o,customContext:n.context?n.context.trim():null,includeProjectTree:!!n.tree,saveTarget:n.save?n.save.trim():null,saveToId:n.saveTo?n.saveTo.trim():null,allowFollowUp:!0,detailLevel:n.detail?n.detail.toLowerCase():`medium`,tasksPath:r.getTasksPath(),projectRoot:r.getProjectRoot()};console.log(t.brand(`Researching: "${c.prompt}"`)),c.taskIds.length>0&&console.log(t.muted(`Task context: ${c.taskIds.join(`, `)}`)),c.filePaths.length>0&&console.log(t.muted(`File context: ${c.filePaths.join(`, `)}`)),c.customContext&&console.log(t.muted(`Custom context: ${c.customContext.substring(0,50)}${c.customContext.length>50?`...`:``}`)),c.includeProjectTree&&console.log(t.muted(`Including project file tree`)),console.log(t.muted(`Detail level: ${c.detailLevel}`));try{let{performResearch:e}=await import(`./research-BRpAIbWg.js`),t={taskIds:c.taskIds,filePaths:c.filePaths,customContext:c.customContext||``,includeProjectTree:c.includeProjectTree,detailLevel:c.detailLevel,projectRoot:c.projectRoot,saveToFile:!!n.saveFile,tag:s},r=await e(c.prompt,t,{commandName:`research`,outputType:`cli`,tag:s},`text`,c.allowFollowUp);if(c.saveToId&&!r.interactiveSaveOccurred)try{let e=c.saveToId.includes(`.`),t=`## Research Query: ${c.prompt}
30
+ This error is related to API keys. Check your environment variables.`)),f()&&console.error(e),process.exit(1)}}),e.command(`scope-up`).description(`Increase task complexity with AI assistance`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`-i, --id <ids>`,`Comma-separated task/subtask IDs to scope up (required)`).option(`-s, --strength <level>`,`Complexity increase strength: light, regular, heavy`,`regular`).option(`-p, --prompt <text>`,`Custom instructions for targeted scope adjustments`).option(`-r, --research`,`Use research AI for more informed adjustments`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{try{let t=X({tasksPath:e.file||!0,tag:e.tag}),n=t.getTasksPath(),r=t.getCurrentTag();await T(r),e.id||(console.error(B.red(`Error: --id parameter is required`)),console.log(B.yellow(`Usage example: taskgraph scope-up --id=1,2,3 --strength=regular`)),process.exit(1));let i=e.id.split(`,`).map(e=>{let t=parseInt(e.trim(),10);return(Number.isNaN(t)||t<=0)&&(console.error(B.red(`Error: Invalid task ID: ${e.trim()}`)),process.exit(1)),t});y(e.strength)||(console.error(B.red(`Error: Invalid strength level: ${e.strength}. Must be one of: light, regular, heavy`)),process.exit(1)),H.existsSync(n)||(console.error(B.red(`Error: Tasks file not found at path: ${n}`)),process.exit(1)),console.log(h.brand(`Scoping up ${i.length} task(s): ${i.join(`, `)}`)),console.log(h.brand(`Strength level: ${e.strength}`)),e.prompt&&console.log(h.brand(`Custom instructions: ${e.prompt}`));let a={projectRoot:t.getProjectRoot(),tag:r,commandName:`scope-up`,outputType:`cli`,research:e.research||!1},o=await re(n,i,e.strength,e.prompt||null,a,`text`);console.log(B.green(`✅ Successfully scoped up ${o.updatedTasks.length} task(s)`))}catch(e){console.error(B.red(`Error: ${e.message}`)),e.message.includes(`not found`)&&(console.log(B.yellow(`
31
+ To fix this issue:`)),console.log(` 1. Run taskgraph list to see all available task IDs`),console.log(` 2. Use valid task IDs with the --id parameter`)),f()&&console.error(e),process.exit(1)}}),e.command(`scope-down`).description(`Decrease task complexity with AI assistance`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`-i, --id <ids>`,`Comma-separated task/subtask IDs to scope down (required)`).option(`-s, --strength <level>`,`Complexity decrease strength: light, regular, heavy`,`regular`).option(`-p, --prompt <text>`,`Custom instructions for targeted scope adjustments`).option(`-r, --research`,`Use research AI for more informed adjustments`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{try{let t=X({tasksPath:e.file||!0,tag:e.tag}),n=t.getTasksPath(),r=t.getCurrentTag();await T(r),e.id||(console.error(B.red(`Error: --id parameter is required`)),console.log(B.yellow(`Usage example: taskgraph scope-down --id=1,2,3 --strength=regular`)),process.exit(1));let i=e.id.split(`,`).map(e=>{let t=parseInt(e.trim(),10);return(Number.isNaN(t)||t<=0)&&(console.error(B.red(`Error: Invalid task ID: ${e.trim()}`)),process.exit(1)),t});y(e.strength)||(console.error(B.red(`Error: Invalid strength level: ${e.strength}. Must be one of: light, regular, heavy`)),process.exit(1)),H.existsSync(n)||(console.error(B.red(`Error: Tasks file not found at path: ${n}`)),process.exit(1)),console.log(h.brand(`Scoping down ${i.length} task(s): ${i.join(`, `)}`)),console.log(h.brand(`Strength level: ${e.strength}`)),e.prompt&&console.log(h.brand(`Custom instructions: ${e.prompt}`));let a={projectRoot:t.getProjectRoot(),tag:r,commandName:`scope-down`,outputType:`cli`,research:e.research||!1},o=await _(n,i,e.strength,e.prompt||null,a,`text`);console.log(B.green(`✅ Successfully scoped down ${o.updatedTasks.length} task(s)`))}catch(e){console.error(B.red(`Error: ${e.message}`)),e.message.includes(`not found`)&&(console.log(B.yellow(`
32
+ To fix this issue:`)),console.log(` 1. Run taskgraph list to see all available task IDs`),console.log(` 2. Use valid task IDs with the --id parameter`)),f()&&console.error(e),process.exit(1)}}),he(e),e.command(`expand`).description(`Expand a task into subtasks using AI`).option(`-i, --id <id>`,`ID of the task to expand`).option(`-a, --all`,`Expand all pending tasks based on complexity analysis`).option(`-n, --num <number>`,`Number of subtasks to generate (uses complexity analysis by default if available)`).option(`-r, --research`,`Enable research-backed generation (web research via Claude Code)`,!1).option(`-p, --prompt <text>`,`Additional context for subtask generation`).option(`-f, --force`,`Force expansion even if subtasks exist`,!1).option(`--file <file>`,`Path to the tasks file (relative to project root)`,i).option(`-cr, --complexity-report <file>`,`Path to the complexity report file (use this to specify the complexity report, not --file)`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async t=>{let n={tasksPath:t.file||!0,tag:t.tag};t.complexityReport&&(n.complexityReportPath=t.complexityReport);let r=X(n),i=r.getCurrentTag();if(await T(i),t.all){console.log(h.brand(`Expanding all pending tasks...`));try{await de(r.getTasksPath(),t.num,t.research,t.prompt,t.force,{projectRoot:r.getProjectRoot(),tag:i,complexityReportPath:r.getComplexityReportPath()})}catch(e){console.error(B.red(`Error expanding all tasks: ${e.message}`)),process.exit(1)}}else if(t.id){t.id||(console.error(B.red(`Error: Task ID is required unless using --all.`)),process.exit(1)),console.log(h.brand(`Expanding task ${t.id}...`));try{await ke(r.getTasksPath(),t.id,t.num,t.research,t.prompt,{projectRoot:r.getProjectRoot(),tag:i,complexityReportPath:r.getComplexityReportPath()},t.force)}catch(e){console.error(B.red(`Error expanding task ${t.id}: ${e.message}`)),process.exit(1)}}else console.error(B.red(`Error: You must specify either a task ID (--id) or --all.`)),e.help()}),e.command(`analyze-complexity`).description(`Analyze tasks and generate expansion recommendations${B.reset(``)}`).option(`-o, --output <file>`,`Output file path for the report`).option(`-m, --model <model>`,`LLM model to use for analysis (defaults to configured model)`).option(`-t, --threshold <number>`,`Minimum complexity score to recommend expansion (1-10)`,`5`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`-r, --research`,`Use configured research model for research-backed complexity analysis`).option(`-i, --id <ids>`,`Comma-separated list of specific task IDs to analyze (e.g., "1,3,5")`).option(`--from <id>`,`Starting task ID in a range to analyze`).option(`--to <id>`,`Ending task ID in a range to analyze`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t={tasksPath:e.file||!0,tag:e.tag};e.output&&(t.complexityReportPath=e.output);let n=X(t);e.model,parseFloat(e.threshold);let r=e.research||!1,i=n.getCurrentTag();await T(i);let a=n.getComplexityReportPath();if(console.log(h.brand(`Analyzing task complexity from: ${n.getTasksPath()}`)),console.log(h.brand(`Output report will be saved to: ${a}`)),e.id)console.log(h.brand(`Analyzing specific task IDs: ${e.id}`));else if(e.from||e.to){let t=e.from?e.from:`first`,n=e.to?e.to:`last`;console.log(h.brand(`Analyzing tasks in range: ${t} to ${n}`))}r&&console.log(h.brand(`Using Claude Code web research for research-backed complexity analysis`)),await pe({...e,output:a,tag:i,projectRoot:n.getProjectRoot(),file:n.getTasksPath()})}),e.command(`research`).description(`Perform AI-powered research queries with project context`).argument(`[prompt]`,`Research prompt to investigate`).option(`--file <file>`,`Path to the tasks file`).option(`-i, --id <ids>`,`Comma-separated task/subtask IDs to include as context (e.g., "15,16.2")`).option(`-f, --files <paths>`,`Comma-separated file paths to include as context`).option(`-c, --context <text>`,`Additional custom context to include in the research prompt`).option(`-t, --tree`,`Include project file tree structure in the research context`).option(`-s, --save <file>`,`Save research results to the specified task/subtask(s)`).option(`-d, --detail <level>`,`Output detail level: low, medium, high`,`medium`).option(`--save-to <id>`,`Automatically save research results to specified task/subtask ID (e.g., "15" or "15.2")`).option(`--save-file`,`Save research results to .taskgraph/docs/research/ directory`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async(e,t)=>{let n=X({tasksPath:t.file||!0,tag:t.tag});(!e||typeof e!=`string`||e.trim().length===0)&&(console.error(B.red(`Error: Research prompt is required and cannot be empty`)),x(),process.exit(1));let r=[`low`,`medium`,`high`];t.detail&&!r.includes(t.detail.toLowerCase())&&(console.error(B.red(`Error: Detail level must be one of: ${r.join(`, `)}`)),process.exit(1));let i=[];if(t.id)try{i=t.id.split(`,`).map(e=>{let t=e.trim();if(!/^\d+(\.\d+)?$/.test(t))throw Error(`Invalid task ID format: "${t}". Expected format: "15" or "15.2"`);return t})}catch(e){console.error(B.red(`Error parsing task IDs: ${e.message}`)),process.exit(1)}let a=[];if(t.files)try{a=t.files.split(`,`).map(e=>{let t=e.trim();if(t.length===0)throw Error(`Empty file path provided`);return t})}catch(e){console.error(B.red(`Error parsing file paths: ${e.message}`)),process.exit(1)}if(t.saveTo){let e=t.saveTo.trim();e.length===0&&(console.error(B.red(`Error: Save-to ID cannot be empty`)),process.exit(1)),/^\d+(\.\d+)?$/.test(e)||(console.error(B.red(`Error: Save-to ID must be in format "15" for task or "15.2" for subtask`)),process.exit(1))}if(t.save){let e=t.save.trim();e.length===0&&(console.error(B.red(`Error: Save target cannot be empty`)),process.exit(1)),(e.includes(`..`)||e.startsWith(`/`))&&(console.error(B.red(`Error: Save path must be relative and cannot contain ".."`)),process.exit(1))}let o=n.getCurrentTag();if(await T(o),i.length>0)try{let e=l(n.getTasksPath(),n.getProjectRoot(),o);(!e||!e.tasks)&&(console.error(B.red(`Error: No valid tasks found in ${n.getTasksPath()} for tag '${o}'`)),process.exit(1))}catch(e){console.error(B.red(`Error reading tasks file: ${e.message}`)),process.exit(1)}if(a.length>0)for(let e of a){let t=V.isAbsolute(e)?e:V.join(n.getProjectRoot(),e);H.existsSync(t)||(console.error(B.red(`Error: File not found: ${e}`)),process.exit(1))}let s={prompt:e.trim(),taskIds:i,filePaths:a,customContext:t.context?t.context.trim():null,includeProjectTree:!!t.tree,saveTarget:t.save?t.save.trim():null,saveToId:t.saveTo?t.saveTo.trim():null,allowFollowUp:!0,detailLevel:t.detail?t.detail.toLowerCase():`medium`,tasksPath:n.getTasksPath(),projectRoot:n.getProjectRoot()};console.log(h.brand(`Researching: "${s.prompt}"`)),s.taskIds.length>0&&console.log(h.muted(`Task context: ${s.taskIds.join(`, `)}`)),s.filePaths.length>0&&console.log(h.muted(`File context: ${s.filePaths.join(`, `)}`)),s.customContext&&console.log(h.muted(`Custom context: ${s.customContext.substring(0,50)}${s.customContext.length>50?`...`:``}`)),s.includeProjectTree&&console.log(h.muted(`Including project file tree`)),console.log(h.muted(`Detail level: ${s.detailLevel}`));try{let{performResearch:e}=await import(`./research-Bol2O66r.js`),n={taskIds:s.taskIds,filePaths:s.filePaths,customContext:s.customContext||``,includeProjectTree:s.includeProjectTree,detailLevel:s.detailLevel,projectRoot:s.projectRoot,saveToFile:!!t.saveFile,tag:o},r=await e(s.prompt,n,{commandName:`research`,outputType:`cli`,tag:o},`text`,s.allowFollowUp);if(s.saveToId&&!r.interactiveSaveOccurred)try{let e=s.saveToId.includes(`.`),t=`## Research Query: ${s.prompt}
33
33
 
34
34
  **Detail Level:** ${r.detailLevel}
35
35
  **Context Size:** ${r.contextSize} characters
@@ -37,7 +37,7 @@ To fix this issue:`)),console.log(` 1. Run taskgraph list to see all available
37
37
 
38
38
  ### Results
39
39
 
40
- ${r.result}`;if(e){let{updateSubtaskById:e}=await import(`./update-subtask-by-id-BOFRADbR.js`);await e(c.tasksPath,c.saveToId,t,!1,{commandName:`research-save`,outputType:`cli`,projectRoot:c.projectRoot,tag:s},`text`),console.log(B.green(`✅ Research saved to subtask ${c.saveToId}`))}else{let e=(await import(`./update-task-by-id-DTHqRii_.js`)).default,n=parseInt(c.saveToId,10);await e(c.tasksPath,n,t,!1,{commandName:`research-save`,outputType:`cli`,projectRoot:c.projectRoot,tag:s},`text`,!0),console.log(B.green(`✅ Research saved to task ${c.saveToId}`))}}catch(e){console.log(B.red(`❌ Error saving to task/subtask: ${e.message}`))}if(c.saveTarget){let e=`# Research Query: ${c.prompt}
40
+ ${r.result}`;if(e){let{updateSubtaskById:e}=await import(`./update-subtask-by-id-D2oia6KG.js`);await e(s.tasksPath,s.saveToId,t,!1,{commandName:`research-save`,outputType:`cli`,projectRoot:s.projectRoot,tag:o},`text`),console.log(B.green(`✅ Research saved to subtask ${s.saveToId}`))}else{let e=(await import(`./update-task-by-id-BvEvVUjJ.js`)).default,n=parseInt(s.saveToId,10);await e(s.tasksPath,n,t,!1,{commandName:`research-save`,outputType:`cli`,projectRoot:s.projectRoot,tag:o},`text`,!0),console.log(B.green(`✅ Research saved to task ${s.saveToId}`))}}catch(e){console.log(B.red(`❌ Error saving to task/subtask: ${e.message}`))}if(s.saveTarget){let e=`# Research Query: ${s.prompt}
41
41
 
42
42
  **Detail Level:** ${r.detailLevel}
43
43
  **Context Size:** ${r.contextSize} characters
@@ -46,33 +46,33 @@ ${r.result}`;if(e){let{updateSubtaskById:e}=await import(`./update-subtask-by-id
46
46
  ## Results
47
47
 
48
48
  ${r.result}
49
- `;V.writeFileSync(c.saveTarget,e,`utf-8`),console.log(B.green(`\n💾 Results saved to: ${c.saveTarget}`))}}catch(e){console.error(B.red(`\n❌ Research failed: ${e.message}`)),process.exit(1)}}),e.command(`clear-subtasks`).description(`Clear subtasks from specified tasks`).option(`-f, --file <file>`,`Path to the tasks file`,r).option(`-i, --id <ids>`,`Task IDs (comma-separated) to clear subtasks from`).option(`--all`,`Clear subtasks from all tasks`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t=e.id,n=e.all,r=X({tasksPath:e.file||!0,tag:e.tag}),i=r.getCurrentTag();if(await T(i),!t&&!n&&(console.error(B.red(`Error: Please specify task IDs with --id=<ids> or use --all to clear all tasks`)),process.exit(1)),n){let e=p(r.getTasksPath(),r.getProjectRoot(),i);(!e||!e.tasks)&&(console.error(B.red(`Error: No valid tasks found`)),process.exit(1));let t=e.tasks.map(e=>e.id).join(`,`);g(r.getTasksPath(),t,{projectRoot:r.getProjectRoot(),tag:i})}else g(r.getTasksPath(),t,{projectRoot:r.getProjectRoot(),tag:i})}),e.command(`add-task`).description(`Add a new task using AI, optionally providing manual details`).option(`-f, --file <file>`,`Path to the tasks file`,r).option(`-p, --prompt <prompt>`,`Description of the task to add (required if not using manual fields)`).option(`-t, --title <title>`,`Task title (for manual task creation)`).option(`-d, --description <description>`,`Task description (for manual task creation)`).option(`--details <details>`,`Implementation details (for manual task creation)`).option(`--dependencies <dependencies>`,`Comma-separated list of task IDs this task depends on`).option(`--priority <priority>`,`Task priority (high, medium, low)`,`medium`).option(`-r, --research`,`Whether to use research capabilities for task creation`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let n=e.title&&e.description;!e.prompt&&!n&&(console.error(B.red(`Error: Either --prompt or both --title and --description must be provided`)),process.exit(1));let i=e.file||r;V.existsSync(i)||(console.error(`❌ No tasks.json file found. Please run "taskgraph init" or create a tasks.json file at ${r}`),process.exit(1));let a=X({tasksPath:e.file||!0,tag:e.tag}),o=a.getProjectRoot(),s=a.getCurrentTag();await T(s);let c=null;n?(c={title:e.title,description:e.description,details:e.details||``,testStrategy:e.testStrategy||``},console.log(t.brand(`Creating task manually with title: "${e.title}"`))):console.log(t.brand(`Creating task with AI using prompt: "${e.prompt}"`));let l=e.dependencies?e.dependencies.split(`,`).map(e=>e.trim()):[];l.length>0&&console.log(t.brand(`Dependencies: [${l.join(`, `)}]`)),e.priority&&console.log(t.brand(`Priority: ${e.priority}`));let u={projectRoot:o,tag:s,commandName:`add-task`,outputType:`cli`};try{let{newTaskId:t,telemetryData:n}=await ae(a.getTasksPath(),e.prompt,l,e.priority,u,`text`,c,e.research)}catch(e){console.error(B.red(`Error adding task: ${e.message}`)),e.details&&console.error(B.red(e.details)),process.exit(1)}}),e.command(`add-dependency`).description(`Add a dependency to a task`).option(`-i, --id <id>`,`Task ID to add dependency to`).option(`-d, --depends-on <id>`,`Task ID that will become a dependency`).option(`-f, --file <file>`,`Path to the tasks file`,r).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t=X({tasksPath:e.file||!0,tag:e.tag}),n=e.id,r=e.dependsOn,i=t.getCurrentTag();await T(i),(!n||!r)&&(console.error(B.red(`Error: Both --id and --depends-on are required`)),process.exit(1));let a=n.includes(`.`)?n:parseInt(n,10),o=r.includes(`.`)?r:parseInt(r,10);await we(t.getTasksPath(),a,o,{projectRoot:t.getProjectRoot(),tag:i})}),e.command(`remove-dependency`).description(`Remove a dependency from a task`).option(`-i, --id <id>`,`Task ID to remove dependency from`).option(`-d, --depends-on <id>`,`Task ID to remove as a dependency`).option(`-f, --file <file>`,`Path to the tasks file`,r).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t=X({tasksPath:e.file||!0,tag:e.tag}),n=e.id,r=e.dependsOn,i=t.getCurrentTag();await T(i),(!n||!r)&&(console.error(B.red(`Error: Both --id and --depends-on are required`)),process.exit(1));let a=n.includes(`.`)?n:parseInt(n,10),o=r.includes(`.`)?r:parseInt(r,10);await xe(t.getTasksPath(),a,o,{projectRoot:t.getProjectRoot(),tag:i})}),e.command(`validate-dependencies`).description(`Identify invalid dependencies without fixing them${B.reset(``)}`).option(`-f, --file <file>`,`Path to the tasks file`,r).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t=X({tasksPath:e.file||!0,tag:e.tag}),n=t.getCurrentTag();await T(n),await A(t.getTasksPath(),{context:{projectRoot:t.getProjectRoot(),tag:n}})}),e.command(`fix-dependencies`).description(`Fix invalid dependencies automatically${B.reset(``)}`).option(`-f, --file <file>`,`Path to the tasks file`,r).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t=X({tasksPath:e.file||!0,tag:e.tag}),n=t.getCurrentTag();await T(n),await I(t.getTasksPath(),{context:{projectRoot:t.getProjectRoot(),tag:n}})}),e.command(`complexity-report`).description(`Display the complexity analysis report${B.reset(``)}`).option(`-f, --file <file>`,`Path to the report file`,m).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t={tag:e.tag};e.file&&e.file!==m&&(t.complexityReportPath=e.file);let n=X(t);await T(n.getCurrentTag()),await N(n.getComplexityReportPath())}),e.command(`add-subtask`).description(`Add a subtask to an existing task`).option(`-f, --file <file>`,`Path to the tasks file`,r).option(`-p, --parent <id>`,`Parent task ID (required)`).option(`-i, --task-id <id>`,`Existing task ID to convert to subtask`).option(`-t, --title <title>`,`Title for the new subtask (when creating a new subtask)`).option(`-d, --description <text>`,`Description for the new subtask`).option(`--details <text>`,`Implementation details for the new subtask`).option(`--dependencies <ids>`,`Comma-separated list of dependency IDs for the new subtask`).option(`-s, --status <status>`,`Status for the new subtask`,`pending`).option(`--generate`,`Regenerate task files after adding subtask`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let n=X({tasksPath:e.file||!0,tag:e.tag}),r=e.parent,a=e.taskId,o=e.generate||!1,s=n.getCurrentTag();await T(s),r||(console.error(B.red(`Error: --parent parameter is required. Please provide a parent task ID.`)),i(),process.exit(1));let c=[];e.dependencies&&(c=e.dependencies.split(`,`).map(e=>e.includes(`.`)?e.trim():parseInt(e.trim(),10)));try{if(a)console.log(t.brand(`Converting task ${a} to a subtask of ${r}...`)),await b(n.getTasksPath(),r,a,null,o,{projectRoot:n.getProjectRoot(),tag:s}),console.log(B.green(`✓ Task ${a} successfully converted to a subtask of task ${r}`));else if(e.title){console.log(t.brand(`Creating new subtask for parent task ${r}...`));let i={title:e.title,description:e.description||``,details:e.details||``,status:e.status||`pending`,dependencies:c},a=await b(n.getTasksPath(),r,null,i,o,{projectRoot:n.getProjectRoot(),tag:s});console.log(B.green(`✓ New subtask ${r}.${a.id} successfully created`)),console.log(U(t.text.bold(`Subtask ${r}.${a.id} Added Successfully`)+`
49
+ `;H.writeFileSync(s.saveTarget,e,`utf-8`),console.log(B.green(`\n💾 Results saved to: ${s.saveTarget}`))}}catch(e){console.error(B.red(`\n❌ Research failed: ${e.message}`)),process.exit(1)}}),e.command(`clear-subtasks`).description(`Clear subtasks from specified tasks`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`-i, --id <ids>`,`Task IDs (comma-separated) to clear subtasks from`).option(`--all`,`Clear subtasks from all tasks`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t=e.id,n=e.all,r=X({tasksPath:e.file||!0,tag:e.tag}),i=r.getCurrentTag();if(await T(i),!t&&!n&&(console.error(B.red(`Error: Please specify task IDs with --id=<ids> or use --all to clear all tasks`)),process.exit(1)),n){let e=l(r.getTasksPath(),r.getProjectRoot(),i);(!e||!e.tasks)&&(console.error(B.red(`Error: No valid tasks found`)),process.exit(1));let t=e.tasks.map(e=>e.id).join(`,`);g(r.getTasksPath(),t,{projectRoot:r.getProjectRoot(),tag:i})}else g(r.getTasksPath(),t,{projectRoot:r.getProjectRoot(),tag:i})}),e.command(`add-task`).description(`Add a new task using AI, optionally providing manual details`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`-p, --prompt <prompt>`,`Description of the task to add (required if not using manual fields)`).option(`-t, --title <title>`,`Task title (for manual task creation)`).option(`-d, --description <description>`,`Task description (for manual task creation)`).option(`--details <details>`,`Implementation details (for manual task creation)`).option(`--dependencies <dependencies>`,`Comma-separated list of task IDs this task depends on`).option(`--priority <priority>`,`Task priority (high, medium, low)`,`medium`).option(`-r, --research`,`Whether to use research capabilities for task creation`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t=e.title&&e.description;!e.prompt&&!t&&(console.error(B.red(`Error: Either --prompt or both --title and --description must be provided`)),process.exit(1));let n=e.file||i;H.existsSync(n)||(console.error(`❌ No tasks.json file found. Please run "taskgraph init" or create a tasks.json file at ${i}`),process.exit(1));let r=X({tasksPath:e.file||!0,tag:e.tag}),a=r.getProjectRoot(),o=r.getCurrentTag();await T(o);let s=null;t?(s={title:e.title,description:e.description,details:e.details||``,testStrategy:e.testStrategy||``},console.log(h.brand(`Creating task manually with title: "${e.title}"`))):console.log(h.brand(`Creating task with AI using prompt: "${e.prompt}"`));let c=e.dependencies?e.dependencies.split(`,`).map(e=>e.trim()):[];c.length>0&&console.log(h.brand(`Dependencies: [${c.join(`, `)}]`)),e.priority&&console.log(h.brand(`Priority: ${e.priority}`));let l={projectRoot:a,tag:o,commandName:`add-task`,outputType:`cli`};try{let{newTaskId:t,telemetryData:n}=await ae(r.getTasksPath(),e.prompt,c,e.priority,l,`text`,s,e.research)}catch(e){console.error(B.red(`Error adding task: ${e.message}`)),e.details&&console.error(B.red(e.details)),process.exit(1)}}),e.command(`add-dependency`).description(`Add a dependency to a task`).option(`-i, --id <id>`,`Task ID to add dependency to`).option(`-d, --depends-on <id>`,`Task ID that will become a dependency`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t=X({tasksPath:e.file||!0,tag:e.tag}),n=e.id,r=e.dependsOn,i=t.getCurrentTag();await T(i),(!n||!r)&&(console.error(B.red(`Error: Both --id and --depends-on are required`)),process.exit(1));let a=n.includes(`.`)?n:parseInt(n,10),o=r.includes(`.`)?r:parseInt(r,10);await we(t.getTasksPath(),a,o,{projectRoot:t.getProjectRoot(),tag:i})}),e.command(`remove-dependency`).description(`Remove a dependency from a task`).option(`-i, --id <id>`,`Task ID to remove dependency from`).option(`-d, --depends-on <id>`,`Task ID to remove as a dependency`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t=X({tasksPath:e.file||!0,tag:e.tag}),n=e.id,r=e.dependsOn,i=t.getCurrentTag();await T(i),(!n||!r)&&(console.error(B.red(`Error: Both --id and --depends-on are required`)),process.exit(1));let a=n.includes(`.`)?n:parseInt(n,10),o=r.includes(`.`)?r:parseInt(r,10);await xe(t.getTasksPath(),a,o,{projectRoot:t.getProjectRoot(),tag:i})}),e.command(`validate-dependencies`).description(`Identify invalid dependencies without fixing them${B.reset(``)}`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t=X({tasksPath:e.file||!0,tag:e.tag}),n=t.getCurrentTag();await T(n),await A(t.getTasksPath(),{context:{projectRoot:t.getProjectRoot(),tag:n}})}),e.command(`fix-dependencies`).description(`Fix invalid dependencies automatically${B.reset(``)}`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t=X({tasksPath:e.file||!0,tag:e.tag}),n=t.getCurrentTag();await T(n),await I(t.getTasksPath(),{context:{projectRoot:t.getProjectRoot(),tag:n}})}),e.command(`complexity-report`).description(`Display the complexity analysis report${B.reset(``)}`).option(`-f, --file <file>`,`Path to the report file`,o).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t={tag:e.tag};e.file&&e.file!==o&&(t.complexityReportPath=e.file);let n=X(t);await T(n.getCurrentTag()),await N(n.getComplexityReportPath())}),e.command(`add-subtask`).description(`Add a subtask to an existing task`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`-p, --parent <id>`,`Parent task ID (required)`).option(`-i, --task-id <id>`,`Existing task ID to convert to subtask`).option(`-t, --title <title>`,`Title for the new subtask (when creating a new subtask)`).option(`-d, --description <text>`,`Description for the new subtask`).option(`--details <text>`,`Implementation details for the new subtask`).option(`--dependencies <ids>`,`Comma-separated list of dependency IDs for the new subtask`).option(`-s, --status <status>`,`Status for the new subtask`,`pending`).option(`--generate`,`Regenerate task files after adding subtask`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let n=X({tasksPath:e.file||!0,tag:e.tag}),r=e.parent,i=e.taskId,a=e.generate||!1,o=n.getCurrentTag();await T(o),r||(console.error(B.red(`Error: --parent parameter is required. Please provide a parent task ID.`)),t(),process.exit(1));let s=[];e.dependencies&&(s=e.dependencies.split(`,`).map(e=>e.includes(`.`)?e.trim():parseInt(e.trim(),10)));try{if(i)console.log(h.brand(`Converting task ${i} to a subtask of ${r}...`)),await b(n.getTasksPath(),r,i,null,a,{projectRoot:n.getProjectRoot(),tag:o}),console.log(B.green(`✓ Task ${i} successfully converted to a subtask of task ${r}`));else if(e.title){console.log(h.brand(`Creating new subtask for parent task ${r}...`));let t={title:e.title,description:e.description||``,details:e.details||``,status:e.status||`pending`,dependencies:s},i=await b(n.getTasksPath(),r,null,t,a,{projectRoot:n.getProjectRoot(),tag:o});console.log(B.green(`✓ New subtask ${r}.${i.id} successfully created`)),console.log(U(h.text.bold(`Subtask ${r}.${i.id} Added Successfully`)+`
50
50
 
51
- `+t.text(`Title: ${a.title}`)+`
52
- `+t.text(`Status: ${R(a.status)}`)+`
53
- `+(c.length>0?t.text(`Dependencies: ${c.join(`, `)}`)+`
51
+ `+h.text(`Title: ${i.title}`)+`
52
+ `+h.text(`Status: ${R(i.status)}`)+`
53
+ `+(s.length>0?h.text(`Dependencies: ${s.join(`, `)}`)+`
54
54
  `:``)+`
55
- `+t.text.bold(`Next Steps:`)+`
55
+ `+h.text.bold(`Next Steps:`)+`
56
56
  `+B.cyan(`1. Run ${B.yellow(`taskgraph show ${r}`)} to see the parent task with all subtasks`)+`
57
- `+B.cyan(`2. Run ${B.yellow(`tm set-status ${r}.${a.id} in-progress`)} to start working on it`),{padding:1,borderColor:`green`,borderStyle:`round`,margin:{top:1}}))}else console.error(B.red(`Error: Either --task-id or --title must be provided.`)),console.log(U(t.text.bold(`Usage Examples:`)+`
57
+ `+B.cyan(`2. Run ${B.yellow(`tm set-status ${r}.${i.id} in-progress`)} to start working on it`),{padding:1,borderColor:`green`,borderStyle:`round`,margin:{top:1}}))}else console.error(B.red(`Error: Either --task-id or --title must be provided.`)),console.log(U(h.text.bold(`Usage Examples:`)+`
58
58
 
59
- `+t.text(`Convert existing task to subtask:`)+`
59
+ `+h.text(`Convert existing task to subtask:`)+`
60
60
  `+B.yellow(` taskgraph add-subtask --parent=5 --task-id=8`)+`
61
61
 
62
- `+t.text(`Create new subtask:`)+`
62
+ `+h.text(`Create new subtask:`)+`
63
63
  `+B.yellow(` taskgraph add-subtask --parent=5 --title="Implement login UI" --description="Create the login form"`)+`
64
64
 
65
- `,{padding:1,borderColor:h,borderStyle:`round`})),process.exit(1)}catch(e){console.error(B.red(`Error: ${e.message}`)),i(),process.exit(1)}}).on(`error`,function(e){console.error(B.red(`Error: ${e.message}`)),i(),process.exit(1)});function i(){console.log(U(`${t.text.bold(`Add Subtask Command Help`)}\n\n${B.cyan(`Usage:`)}\n taskgraph add-subtask --parent=<id> [options]\n\n${B.cyan(`Options:`)}\n -p, --parent <id> Parent task ID (required)\n -i, --task-id <id> Existing task ID to convert to subtask\n -t, --title <title> Title for the new subtask\n -d, --description <text> Description for the new subtask\n --details <text> Implementation details for the new subtask\n --dependencies <ids> Comma-separated list of dependency IDs\n -s, --status <status> Status for the new subtask (default: "pending")\n -f, --file <file> Path to the tasks file (default: "${r}")\n --generate Regenerate task files after adding subtask\n\n${B.cyan(`Examples:`)}\n taskgraph add-subtask --parent=5 --task-id=8\n taskgraph add-subtask -p 5 -t "Implement login UI" -d "Create the login form" --generate`,{padding:1,borderColor:h,borderStyle:`round`}))}e.command(`remove-subtask`).description(`Remove a subtask from its parent task`).option(`-f, --file <file>`,`Path to the tasks file`,r).option(`-i, --id <id>`,`Subtask ID(s) to remove in format "parentId.subtaskId" (can be comma-separated for multiple subtasks)`).option(`-c, --convert`,`Convert the subtask to a standalone task instead of deleting it`).option(`--generate`,`Regenerate task files after removing subtask`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let n=X({tasksPath:e.file||!0,tag:e.tag}),r=e.id,i=e.convert||!1,o=e.generate||!1,s=n.getCurrentTag();r||(console.error(B.red(`Error: --id parameter is required. Please provide subtask ID(s) in format "parentId.subtaskId".`)),a(),process.exit(1));try{let e=r.split(`,`).map(e=>e.trim());for(let r of e){r.includes(`.`)||(console.error(B.red(`Error: Subtask ID "${r}" must be in format "parentId.subtaskId"`)),a(),process.exit(1)),console.log(t.brand(`Removing subtask ${r}...`)),i&&console.log(t.brand(`The subtask will be converted to a standalone task`));let e=await ce(n.getTasksPath(),r,i,o,{projectRoot:n.getProjectRoot(),tag:s});i&&e?console.log(U(t.text.bold(`Subtask ${r} Converted to Task #${e.id}`)+`
65
+ `,{padding:1,borderColor:c,borderStyle:`round`})),process.exit(1)}catch(e){console.error(B.red(`Error: ${e.message}`)),t(),process.exit(1)}}).on(`error`,function(e){console.error(B.red(`Error: ${e.message}`)),t(),process.exit(1)});function t(){console.log(U(`${h.text.bold(`Add Subtask Command Help`)}\n\n${B.cyan(`Usage:`)}\n taskgraph add-subtask --parent=<id> [options]\n\n${B.cyan(`Options:`)}\n -p, --parent <id> Parent task ID (required)\n -i, --task-id <id> Existing task ID to convert to subtask\n -t, --title <title> Title for the new subtask\n -d, --description <text> Description for the new subtask\n --details <text> Implementation details for the new subtask\n --dependencies <ids> Comma-separated list of dependency IDs\n -s, --status <status> Status for the new subtask (default: "pending")\n -f, --file <file> Path to the tasks file (default: "${i}")\n --generate Regenerate task files after adding subtask\n\n${B.cyan(`Examples:`)}\n taskgraph add-subtask --parent=5 --task-id=8\n taskgraph add-subtask -p 5 -t "Implement login UI" -d "Create the login form" --generate`,{padding:1,borderColor:c,borderStyle:`round`}))}e.command(`remove-subtask`).description(`Remove a subtask from its parent task`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`-i, --id <id>`,`Subtask ID(s) to remove in format "parentId.subtaskId" (can be comma-separated for multiple subtasks)`).option(`-c, --convert`,`Convert the subtask to a standalone task instead of deleting it`).option(`--generate`,`Regenerate task files after removing subtask`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t=X({tasksPath:e.file||!0,tag:e.tag}),r=e.id,i=e.convert||!1,a=e.generate||!1,o=t.getCurrentTag();r||(console.error(B.red(`Error: --id parameter is required. Please provide subtask ID(s) in format "parentId.subtaskId".`)),n(),process.exit(1));try{let e=r.split(`,`).map(e=>e.trim());for(let r of e){r.includes(`.`)||(console.error(B.red(`Error: Subtask ID "${r}" must be in format "parentId.subtaskId"`)),n(),process.exit(1)),console.log(h.brand(`Removing subtask ${r}...`)),i&&console.log(h.brand(`The subtask will be converted to a standalone task`));let e=await ce(t.getTasksPath(),r,i,a,{projectRoot:t.getProjectRoot(),tag:o});i&&e?console.log(U(h.text.bold(`Subtask ${r} Converted to Task #${e.id}`)+`
66
66
 
67
- `+t.text(`Title: ${e.title}`)+`
68
- `+t.text(`Status: ${R(e.status)}`)+`
69
- `+t.text(`Dependencies: ${e.dependencies.join(`, `)}`)+`
67
+ `+h.text(`Title: ${e.title}`)+`
68
+ `+h.text(`Status: ${R(e.status)}`)+`
69
+ `+h.text(`Dependencies: ${e.dependencies.join(`, `)}`)+`
70
70
 
71
- `+t.text.bold(`Next Steps:`)+`
71
+ `+h.text.bold(`Next Steps:`)+`
72
72
  `+B.cyan(`1. Run ${B.yellow(`taskgraph show ${e.id}`)} to see details of the new task`)+`
73
- `+B.cyan(`2. Run ${B.yellow(`tm set-status ${e.id} in-progress`)} to start working on it`),{padding:1,borderColor:`green`,borderStyle:`round`,margin:{top:1}})):console.log(U(t.text.bold(`Subtask ${r} Removed`)+`
73
+ `+B.cyan(`2. Run ${B.yellow(`tm set-status ${e.id} in-progress`)} to start working on it`),{padding:1,borderColor:`green`,borderStyle:`round`,margin:{top:1}})):console.log(U(h.text.bold(`Subtask ${r} Removed`)+`
74
74
 
75
- `+t.text(`The subtask has been successfully deleted.`),{padding:1,borderColor:`green`,borderStyle:`round`,margin:{top:1}}))}}catch(e){console.error(B.red(`Error: ${e.message}`)),a(),process.exit(1)}}).on(`error`,function(e){console.error(B.red(`Error: ${e.message}`)),a(),process.exit(1)});function a(){console.log(U(t.text.bold(`Remove Subtask Command Help`)+`
75
+ `+h.text(`The subtask has been successfully deleted.`),{padding:1,borderColor:`green`,borderStyle:`round`,margin:{top:1}}))}}catch(e){console.error(B.red(`Error: ${e.message}`)),n(),process.exit(1)}}).on(`error`,function(e){console.error(B.red(`Error: ${e.message}`)),n(),process.exit(1)});function n(){console.log(U(h.text.bold(`Remove Subtask Command Help`)+`
76
76
 
77
77
  `+B.cyan(`Usage:`)+`
78
78
  taskgraph remove-subtask --id=<parentId.subtaskId> [options]
@@ -80,19 +80,19 @@ ${r.result}
80
80
  `+B.cyan(`Options:`)+`
81
81
  -i, --id <id> Subtask ID(s) to remove in format "parentId.subtaskId" (can be comma-separated, required)
82
82
  -c, --convert Convert the subtask to a standalone task instead of deleting it
83
- -f, --file <file> Path to the tasks file (default: "`+r+`")
83
+ -f, --file <file> Path to the tasks file (default: "`+i+`")
84
84
  --skip-generate Skip regenerating task files
85
85
 
86
86
  `+B.cyan(`Examples:`)+`
87
87
  taskgraph remove-subtask --id=5.2
88
88
  taskgraph remove-subtask --id=5.2,6.3,7.1
89
- taskgraph remove-subtask --id=5.2 --convert`,{padding:1,borderColor:h,borderStyle:`round`}))}function l(){console.log(U(t.text.bold(`Add Tag Command Help`)+`
89
+ taskgraph remove-subtask --id=5.2 --convert`,{padding:1,borderColor:c,borderStyle:`round`}))}function a(){console.log(U(h.text.bold(`Add Tag Command Help`)+`
90
90
 
91
91
  `+B.cyan(`Usage:`)+`
92
92
  taskgraph add-tag <tagName> [options]
93
93
 
94
94
  `+B.cyan(`Options:`)+`
95
- -f, --file <file> Path to the tasks file (default: "`+r+`")
95
+ -f, --file <file> Path to the tasks file (default: "`+i+`")
96
96
  --copy-from-current Copy tasks from the current tag to the new tag
97
97
  --copy-from <tag> Copy tasks from the specified tag to the new tag
98
98
  -d, --description <text> Optional description for the tag
@@ -101,13 +101,13 @@ ${r.result}
101
101
  taskgraph add-tag feature-xyz
102
102
  taskgraph add-tag feature-xyz --copy-from-current
103
103
  taskgraph add-tag feature-xyz --copy-from master
104
- taskgraph add-tag feature-xyz -d "Feature XYZ development"`,{padding:1,borderColor:h,borderStyle:`round`}))}function u(){console.log(U(t.text.bold(`Delete Tag Command Help`)+`
104
+ taskgraph add-tag feature-xyz -d "Feature XYZ development"`,{padding:1,borderColor:c,borderStyle:`round`}))}function u(){console.log(U(h.text.bold(`Delete Tag Command Help`)+`
105
105
 
106
106
  `+B.cyan(`Usage:`)+`
107
107
  taskgraph delete-tag <tagName> [options]
108
108
 
109
109
  `+B.cyan(`Options:`)+`
110
- -f, --file <file> Path to the tasks file (default: "`+r+`")
110
+ -f, --file <file> Path to the tasks file (default: "`+i+`")
111
111
  -y, --yes Skip confirmation prompts
112
112
 
113
113
  `+B.cyan(`Examples:`)+`
@@ -115,13 +115,13 @@ ${r.result}
115
115
  taskgraph delete-tag feature-xyz --yes
116
116
 
117
117
  `+B.yellow(`Warning:`)+`
118
- This will permanently delete the tag and all its tasks!`,{padding:1,borderColor:h,borderStyle:`round`}))}function f(){console.log(U(t.text.bold(`Use Tag Command Help`)+`
118
+ This will permanently delete the tag and all its tasks!`,{padding:1,borderColor:c,borderStyle:`round`}))}function m(){console.log(U(h.text.bold(`Use Tag Command Help`)+`
119
119
 
120
120
  `+B.cyan(`Usage:`)+`
121
121
  taskgraph use-tag <tagName> [options]
122
122
 
123
123
  `+B.cyan(`Options:`)+`
124
- -f, --file <file> Path to the tasks file (default: "`+r+`")
124
+ -f, --file <file> Path to the tasks file (default: "`+i+`")
125
125
 
126
126
  `+B.cyan(`Examples:`)+`
127
127
  taskgraph use-tag feature-xyz
@@ -129,7 +129,7 @@ ${r.result}
129
129
 
130
130
  `+B.cyan(`Related Commands:`)+`
131
131
  taskgraph tags List all available tags
132
- taskgraph add-tag <name> Create a new tag`,{padding:1,borderColor:h,borderStyle:`round`}))}function x(){console.log(U(t.text.bold(`Research Command Help`)+`
132
+ taskgraph add-tag <name> Create a new tag`,{padding:1,borderColor:c,borderStyle:`round`}))}function x(){console.log(U(h.text.bold(`Research Command Help`)+`
133
133
 
134
134
  `+B.cyan(`Usage:`)+`
135
135
  taskgraph research "<query>" [options]
@@ -152,7 +152,7 @@ ${r.result}
152
152
  taskgraph research "How should I implement user authentication?"
153
153
  taskgraph research "What's the best approach?" --id=15,23.2
154
154
  taskgraph research "How does auth work?" --files=src/auth.js --tree
155
- taskgraph research "Implementation steps?" --save-to=15.2 --detail=high`,{padding:1,borderColor:h,borderStyle:`round`}))}return e.command(`remove-task`).description(`Remove one or more tasks or subtasks permanently`).option(`-i, --id <ids>`,`ID(s) of the task(s) or subtask(s) to remove (e.g., "5", "5.2", or "5,6.1,7")`).option(`-f, --file <file>`,`Path to the tasks file`,r).option(`-y, --yes`,`Skip confirmation prompt`,!1).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let n=X({tasksPath:e.file||!0,tag:e.tag}),r=e.id,i=n.getCurrentTag();await T(i),r||(console.error(B.red(`Error: Task ID(s) are required`)),console.error(B.yellow(`Usage: taskgraph remove-task --id=<taskId1,taskId2...>`)),process.exit(1));let a=r.split(`,`).map(e=>e.trim()).filter(Boolean);a.length===0&&(console.error(B.red(`Error: No valid task IDs provided.`)),process.exit(1));try{let r=n.getTasksPath(),s=p(r,n.getProjectRoot(),i);(!s||!s.tasks)&&(console.error(B.red(`Error: No valid tasks found in ${r}`)),process.exit(1));let c=[],l=[],u=0,d=[];for(let e of a)if(!M(s.tasks,e))l.push(e);else{let t=o(s.tasks,e).task;if(t){if(c.push({id:e,task:t}),!t.isSubtask){t.subtasks&&t.subtasks.length>0&&(u+=t.subtasks.length);let n=s.tasks.filter(t=>t.dependencies&&t.dependencies.includes(parseInt(e,10)));n.length>0&&d.push(` - Task ${e}: ${n.length} dependent tasks (${n.map(e=>e.id).join(`, `)})`)}}else l.push(`${e} (error finding details)`)}if(l.length>0&&console.warn(B.yellow(`Warning: The following task IDs were not found: ${l.join(`, `)}`)),c.length===0&&(console.log(t.brand(`No existing tasks found to remove.`)),process.exit(0)),!e.yes){console.log(),console.log(B.red.bold(`⚠️ WARNING: This will permanently delete the following ${c.length} item(s):`)),console.log(),c.forEach(({id:e,task:n})=>{n&&(n.isSubtask?(console.log(t.text(` Subtask ${e}: ${n.title||`(no title)`}`)),n.parentTask&&console.log(t.muted(` (Parent: ${n.parentTask.id} - ${n.parentTask.title||`(no title)`})`))):console.log(t.text.bold(` Task ${e}: ${n.title||`(no title)`}`)))}),u>0&&console.log(B.yellow(`⚠️ This will also delete ${u} subtasks associated with the selected main tasks!`)),d.length>0&&(console.log(B.yellow(`⚠️ Warning: Dependencies on the following tasks will be removed:`)),d.forEach(e=>console.log(B.yellow(e)))),console.log();let{confirm:e}=await G.prompt([{type:`confirm`,name:`confirm`,message:B.red.bold(`Are you sure you want to permanently delete these ${c.length} item(s)?`),default:!1}]);e||(console.log(t.brand(`Task deletion cancelled.`)),process.exit(0))}let f=Oe(`Removing ${c.length} task(s)/subtask(s)...`),m=c.map(({id:e})=>e).join(`,`),h=await te(n.getTasksPath(),m,{projectRoot:n.getProjectRoot(),tag:i});S(f),h.success?console.log(U(B.green(`Successfully removed ${h.removedTasks.length} task(s)/subtask(s).`)+(h.message?`\n\nDetails:\n${h.message}`:``)+(h.error?`\n\nWarnings:\n${B.yellow(h.error)}`:``),{padding:1,borderColor:`green`,borderStyle:`round`})):(console.error(U(B.red(`Operation completed with errors. Removed ${h.removedTasks.length} task(s)/subtask(s).`)+(h.message?`\n\nDetails:\n${h.message}`:``)+(h.error?`\n\nErrors:\n${B.red(h.error)}`:``),{padding:1,borderColor:`red`,borderStyle:`round`})),process.exit(1)),l.length>0&&(console.warn(B.yellow(`Note: The following IDs were not found initially and were skipped: ${l.join(`, `)}`)),h.removedTasks.length===0&&process.exit(1))}catch(e){console.error(B.red(`Error: ${e.message||`An unknown error occurred`}`)),process.exit(1)}}),e.command(`init`).description(`Initialize a new project with TaskGraph structure`).option(`-y, --yes`,`Skip prompts and use default values`).option(`-n, --name <name>`,`Project name`).option(`-d, --description <description>`,`Project description`).option(`-v, --version <version>`,`Project version`,`0.1.0`).option(`-a, --author <author>`,`Author name`).option(`-r, --rules <rules...>`,`Rule profiles to install (claude). Accepts comma or space separated values.`).option(`--skip-install`,`Skip installing dependencies`).option(`--dry-run`,`Show what would be done without making changes`).option(`--aliases`,`Add shell aliases (tm, taskgraph)`).option(`--no-aliases`,`Skip shell aliases (tm, taskgraph)`).option(`--git`,`Initialize Git repository`).option(`--no-git`,`Skip Git repository initialization`).option(`--git-tasks`,`Store tasks in Git`).option(`--no-git-tasks`,`No Git storage of tasks`).action(async e=>{let t=z,n=!1;if(e.rules&&Array.isArray(e.rules)){let r=e.rules.flatMap(e=>e.split(`,`)).map(e=>e.trim()).filter(Boolean),i=je(r);i.length>0&&(console.error(B.red(`Unsupported rule profile(s): ${i.join(`, `)}. TaskGraph supports Claude Code only; valid options: ${z.join(`, `)}`)),process.exit(1)),r.length>0&&(t=r,n=!0)}e.rules=t,e.rulesExplicitlyProvided=n;try{await Me(e)}catch(e){console.error(B.red(`Error during initialization: ${e.message}`)),process.exit(1)}}),e.command(`models`).description(`Manage AI model configurations (Claude Code models)`).option(`--set-main <model_id>`,`Set the primary model for task generation/updates`).option(`--set-research <model_id>`,`Set the model for research-backed operations`).option(`--set-fallback <model_id>`,`Set the model to use if the primary fails`).option(`--setup`,`Run interactive setup to configure models`).addOption(new W(`--claude-code`).hideHelp()).addOption(new W(`--openrouter`).hideHelp()).addOption(new W(`--ollama`).hideHelp()).addOption(new W(`--bedrock`).hideHelp()).addOption(new W(`--azure`).hideHelp()).addOption(new W(`--vertex`).hideHelp()).addOption(new W(`--gemini-cli`).hideHelp()).addOption(new W(`--codex-cli`).hideHelp()).addOption(new W(`--lmstudio`).hideHelp()).addOption(new W(`--openai-compatible`).hideHelp()).addOption(new W(`--baseURL <url>`).hideHelp()).addHelpText(`after`,`
155
+ taskgraph research "Implementation steps?" --save-to=15.2 --detail=high`,{padding:1,borderColor:c,borderStyle:`round`}))}return e.command(`remove-task`).description(`Remove one or more tasks or subtasks permanently`).option(`-i, --id <ids>`,`ID(s) of the task(s) or subtask(s) to remove (e.g., "5", "5.2", or "5,6.1,7")`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`-y, --yes`,`Skip confirmation prompt`,!1).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t=X({tasksPath:e.file||!0,tag:e.tag}),n=e.id,i=t.getCurrentTag();await T(i),n||(console.error(B.red(`Error: Task ID(s) are required`)),console.error(B.yellow(`Usage: taskgraph remove-task --id=<taskId1,taskId2...>`)),process.exit(1));let a=n.split(`,`).map(e=>e.trim()).filter(Boolean);a.length===0&&(console.error(B.red(`Error: No valid task IDs provided.`)),process.exit(1));try{let n=t.getTasksPath(),o=l(n,t.getProjectRoot(),i);(!o||!o.tasks)&&(console.error(B.red(`Error: No valid tasks found in ${n}`)),process.exit(1));let s=[],c=[],u=0,d=[];for(let e of a)if(!M(o.tasks,e))c.push(e);else{let t=r(o.tasks,e).task;if(t){if(s.push({id:e,task:t}),!t.isSubtask){t.subtasks&&t.subtasks.length>0&&(u+=t.subtasks.length);let n=o.tasks.filter(t=>t.dependencies&&t.dependencies.includes(parseInt(e,10)));n.length>0&&d.push(` - Task ${e}: ${n.length} dependent tasks (${n.map(e=>e.id).join(`, `)})`)}}else c.push(`${e} (error finding details)`)}if(c.length>0&&console.warn(B.yellow(`Warning: The following task IDs were not found: ${c.join(`, `)}`)),s.length===0&&(console.log(h.brand(`No existing tasks found to remove.`)),process.exit(0)),!e.yes){console.log(),console.log(B.red.bold(`⚠️ WARNING: This will permanently delete the following ${s.length} item(s):`)),console.log(),s.forEach(({id:e,task:t})=>{t&&(t.isSubtask?(console.log(h.text(` Subtask ${e}: ${t.title||`(no title)`}`)),t.parentTask&&console.log(h.muted(` (Parent: ${t.parentTask.id} - ${t.parentTask.title||`(no title)`})`))):console.log(h.text.bold(` Task ${e}: ${t.title||`(no title)`}`)))}),u>0&&console.log(B.yellow(`⚠️ This will also delete ${u} subtasks associated with the selected main tasks!`)),d.length>0&&(console.log(B.yellow(`⚠️ Warning: Dependencies on the following tasks will be removed:`)),d.forEach(e=>console.log(B.yellow(e)))),console.log();let{confirm:e}=await G.prompt([{type:`confirm`,name:`confirm`,message:B.red.bold(`Are you sure you want to permanently delete these ${s.length} item(s)?`),default:!1}]);e||(console.log(h.brand(`Task deletion cancelled.`)),process.exit(0))}let f=Oe(`Removing ${s.length} task(s)/subtask(s)...`),p=s.map(({id:e})=>e).join(`,`),m=await te(t.getTasksPath(),p,{projectRoot:t.getProjectRoot(),tag:i});S(f),m.success?console.log(U(B.green(`Successfully removed ${m.removedTasks.length} task(s)/subtask(s).`)+(m.message?`\n\nDetails:\n${m.message}`:``)+(m.error?`\n\nWarnings:\n${B.yellow(m.error)}`:``),{padding:1,borderColor:`green`,borderStyle:`round`})):(console.error(U(B.red(`Operation completed with errors. Removed ${m.removedTasks.length} task(s)/subtask(s).`)+(m.message?`\n\nDetails:\n${m.message}`:``)+(m.error?`\n\nErrors:\n${B.red(m.error)}`:``),{padding:1,borderColor:`red`,borderStyle:`round`})),process.exit(1)),c.length>0&&(console.warn(B.yellow(`Note: The following IDs were not found initially and were skipped: ${c.join(`, `)}`)),m.removedTasks.length===0&&process.exit(1))}catch(e){console.error(B.red(`Error: ${e.message||`An unknown error occurred`}`)),process.exit(1)}}),e.command(`init`).description(`Initialize a new project with TaskGraph structure`).option(`-y, --yes`,`Skip prompts and use default values`).option(`-n, --name <name>`,`Project name`).option(`-d, --description <description>`,`Project description`).option(`-v, --version <version>`,`Project version`,`0.1.0`).option(`-a, --author <author>`,`Author name`).option(`-r, --rules <rules...>`,`Rule profiles to install (claude). Accepts comma or space separated values.`).option(`--skip-install`,`Skip installing dependencies`).option(`--dry-run`,`Show what would be done without making changes`).option(`--aliases`,`Add shell aliases (tm, taskgraph)`).option(`--no-aliases`,`Skip shell aliases (tm, taskgraph)`).option(`--git`,`Initialize Git repository`).option(`--no-git`,`Skip Git repository initialization`).option(`--git-tasks`,`Store tasks in Git`).option(`--no-git-tasks`,`No Git storage of tasks`).action(async e=>{let t=z,n=!1;if(e.rules&&Array.isArray(e.rules)){let r=e.rules.flatMap(e=>e.split(`,`)).map(e=>e.trim()).filter(Boolean),i=je(r);i.length>0&&(console.error(B.red(`Unsupported rule profile(s): ${i.join(`, `)}. TaskGraph supports Claude Code only; valid options: ${z.join(`, `)}`)),process.exit(1)),r.length>0&&(t=r,n=!0)}e.rules=t,e.rulesExplicitlyProvided=n;try{await Me(e)}catch(e){console.error(B.red(`Error during initialization: ${e.message}`)),process.exit(1)}}),e.command(`models`).description(`Manage AI model configurations (Claude Code models)`).option(`--set-main <model_id>`,`Set the primary model for task generation/updates`).option(`--set-research <model_id>`,`Set the model for research-backed operations`).option(`--set-fallback <model_id>`,`Set the model to use if the primary fails`).option(`--setup`,`Run interactive setup to configure models`).addOption(new W(`--claude-code`).hideHelp()).addOption(new W(`--openrouter`).hideHelp()).addOption(new W(`--ollama`).hideHelp()).addOption(new W(`--bedrock`).hideHelp()).addOption(new W(`--azure`).hideHelp()).addOption(new W(`--vertex`).hideHelp()).addOption(new W(`--gemini-cli`).hideHelp()).addOption(new W(`--codex-cli`).hideHelp()).addOption(new W(`--lmstudio`).hideHelp()).addOption(new W(`--openai-compatible`).hideHelp()).addOption(new W(`--baseURL <url>`).hideHelp()).addHelpText(`after`,`
156
156
  TaskGraph uses Claude Code. Available models: opus, sonnet, haiku.
157
157
 
158
158
  Examples:
@@ -160,71 +160,71 @@ Examples:
160
160
  $ taskgraph models --set-main sonnet # Set main model
161
161
  $ taskgraph models --set-research opus # Set research model
162
162
  $ taskgraph models --set-fallback haiku # Set fallback
163
- $ taskgraph models --setup # Run interactive setup`).action(async e=>{let r=X({tasksPath:e.file||!1}).getProjectRoot();if([`openrouter`,`ollama`,`bedrock`,`azure`,`vertex`,`geminiCli`,`codexCli`,`lmstudio`,`openaiCompatible`,`baseURL`].filter(t=>e[t]).length>0&&(console.error(B.red(`Error: TaskGraph now uses Claude Code only, so provider flags such as --ollama, --openrouter and --baseURL are no longer supported.`)),console.error(B.yellow(`Choose one of the Claude Code models: taskgraph models --set-main <opus|sonnet|haiku>`)),process.exit(1)),e.setup){console.log(t.brand(`Starting interactive model setup...`));try{await ie(r)}catch(e){console.error(B.red(`
164
- Interactive setup failed unexpectedly:`),e.message)}return}let i=[[`main`,e.setMain],[`research`,e.setResearch],[`fallback`,e.setFallback]].filter(([,e])=>e);if(i.length>0){let e=!1;for(let[t,n]of i){let i=await oe(t,n,{projectRoot:r});i.success?(console.log(B.green(`✅ ${i.data.message}`)),e=!0):console.error(B.red(`❌ Error setting ${t} model: ${i.error.message}`))}e?console.log(t.brand(`
163
+ $ taskgraph models --setup # Run interactive setup`).action(async e=>{let t=X({tasksPath:e.file||!1}).getProjectRoot();if([`openrouter`,`ollama`,`bedrock`,`azure`,`vertex`,`geminiCli`,`codexCli`,`lmstudio`,`openaiCompatible`,`baseURL`].filter(t=>e[t]).length>0&&(console.error(B.red(`Error: TaskGraph now uses Claude Code only, so provider flags such as --ollama, --openrouter and --baseURL are no longer supported.`)),console.error(B.yellow(`Choose one of the Claude Code models: taskgraph models --set-main <opus|sonnet|haiku>`)),process.exit(1)),e.setup){console.log(h.brand(`Starting interactive model setup...`));try{await ie(t)}catch(e){console.error(B.red(`
164
+ Interactive setup failed unexpectedly:`),e.message)}return}let n=[[`main`,e.setMain],[`research`,e.setResearch],[`fallback`,e.setFallback]].filter(([,e])=>e);if(n.length>0){let e=!1;for(let[r,i]of n){let n=await oe(r,i,{projectRoot:t});n.success?(console.log(B.green(`✅ ${n.data.message}`)),e=!0):console.error(B.red(`❌ Error setting ${r} model: ${n.error.message}`))}e?console.log(h.brand(`
165
165
  Model configuration updated.`)):console.log(B.yellow(`
166
- No model configuration changes were made (or errors occurred).`));return}console.log(t.brand(`Fetching current model configuration...`));let a=await be({projectRoot:r}),o=await se({projectRoot:r});if(a.success?k(a.data,o.data?.models||[]):console.error(B.red(`❌ Error fetching configuration: ${a.error.message}`)),o.success){let e=a.success?[a.data.activeModels.main.modelId,a.data.activeModels.research.modelId,a.data.activeModels.fallback?.modelId].filter(Boolean):[];C(o.data.models.filter(t=>!e.includes(t.modelId)))}else console.error(B.yellow(`⚠️ Warning: Could not display available models: ${o.error.message}`));n(r)||console.log(B.yellow(`
167
- Hint: Run 'taskgraph models --setup' to create or update your configuration.`))}),e.command(`lang`).description(`Manage response language settings`).option(`--response <response_language>`,`Set the response language`).option(`--setup`,`Run interactive setup to configure response language`).action(async e=>{let n=X({}).getProjectRoot(),{response:r,setup:i}=e,a=r===void 0?`English`:r;if(i){console.log(t.brand(`Starting interactive response language setup...`));try{let e=await G.prompt([{type:`input`,name:`responseLanguage`,message:`Input your preferred response language`,default:`English`}]);console.log(t.brand(`Response language set to:`,e.responseLanguage)),a=e.responseLanguage}catch(e){console.error(B.red(`\\nInteractive setup failed unexpectedly:`),e.message)}}let o=Ae(a,{projectRoot:n});o.success?console.log(B.green(`✅ ${o.data.message}`)):(console.error(B.red(`❌ Error setting response language: ${o.error.message}`)),process.exit(1))}),e.command(`move`).description(`Move tasks between tags or reorder within tags. Supports cross-tag moves with dependency resolution options.`).option(`-f, --file <file>`,`Path to the tasks file`,r).option(`--from <id>`,`ID of the task/subtask to move (e.g., "5" or "5.2"). Can be comma-separated to move multiple tasks (e.g., "5,6,7")`).option(`--to <id>`,`ID of the destination (e.g., "7" or "7.3"). Must match the number of source IDs if comma-separated`).option(`--tag <tag>`,`Specify tag context for task operations`).option(`--from-tag <tag>`,`Source tag for cross-tag moves`).option(`--to-tag <tag>`,`Target tag for cross-tag moves`).option(`--with-dependencies`,`Move dependent tasks along with main task`).option(`--ignore-dependencies`,`Break cross-tag dependencies during move`).action(async e=>{function n(){console.log(t.text.bold(`Move Command Help`)+`
166
+ No model configuration changes were made (or errors occurred).`));return}console.log(h.brand(`Fetching current model configuration...`));let r=await be({projectRoot:t}),i=await se({projectRoot:t});if(r.success?k(r.data,i.data?.models||[]):console.error(B.red(`❌ Error fetching configuration: ${r.error.message}`)),i.success){let e=r.success?[r.data.activeModels.main.modelId,r.data.activeModels.research.modelId,r.data.activeModels.fallback?.modelId].filter(Boolean):[];C(i.data.models.filter(t=>!e.includes(t.modelId)))}else console.error(B.yellow(`⚠️ Warning: Could not display available models: ${i.error.message}`));s(t)||console.log(B.yellow(`
167
+ Hint: Run 'taskgraph models --setup' to create or update your configuration.`))}),e.command(`lang`).description(`Manage response language settings`).option(`--response <response_language>`,`Set the response language`).option(`--setup`,`Run interactive setup to configure response language`).action(async e=>{let t=X({}).getProjectRoot(),{response:n,setup:r}=e,i=n===void 0?`English`:n;if(r){console.log(h.brand(`Starting interactive response language setup...`));try{let e=await G.prompt([{type:`input`,name:`responseLanguage`,message:`Input your preferred response language`,default:`English`}]);console.log(h.brand(`Response language set to:`,e.responseLanguage)),i=e.responseLanguage}catch(e){console.error(B.red(`\\nInteractive setup failed unexpectedly:`),e.message)}}let a=Ae(i,{projectRoot:t});a.success?console.log(B.green(`✅ ${a.data.message}`)):(console.error(B.red(`❌ Error setting response language: ${a.error.message}`)),process.exit(1))}),e.command(`move`).description(`Move tasks between tags or reorder within tags. Supports cross-tag moves with dependency resolution options.`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`--from <id>`,`ID of the task/subtask to move (e.g., "5" or "5.2"). Can be comma-separated to move multiple tasks (e.g., "5,6,7")`).option(`--to <id>`,`ID of the destination (e.g., "7" or "7.3"). Must match the number of source IDs if comma-separated`).option(`--tag <tag>`,`Specify tag context for task operations`).option(`--from-tag <tag>`,`Source tag for cross-tag moves`).option(`--to-tag <tag>`,`Target tag for cross-tag moves`).option(`--with-dependencies`,`Move dependent tasks along with main task`).option(`--ignore-dependencies`,`Break cross-tag dependencies during move`).action(async e=>{function t(){console.log(h.text.bold(`Move Command Help`)+`
168
168
 
169
169
  `+B.cyan(`Move tasks between tags or reorder within tags.`)+`
170
170
 
171
171
  `+B.yellow.bold(`Within-Tag Moves:`)+`
172
- `+t.text(` taskgraph move --from=5 --to=7`)+`
173
- `+t.text(` taskgraph move --from=5.2 --to=7.3`)+`
174
- `+t.text(` taskgraph move --from=5,6,7 --to=10,11,12`)+`
172
+ `+h.text(` taskgraph move --from=5 --to=7`)+`
173
+ `+h.text(` taskgraph move --from=5.2 --to=7.3`)+`
174
+ `+h.text(` taskgraph move --from=5,6,7 --to=10,11,12`)+`
175
175
 
176
176
  `+B.yellow.bold(`Cross-Tag Moves:`)+`
177
- `+t.text(` taskgraph move --from=5 --from-tag=backlog --to-tag=in-progress`)+`
178
- `+t.text(` taskgraph move --from=5,6 --from-tag=backlog --to-tag=done`)+`
177
+ `+h.text(` taskgraph move --from=5 --from-tag=backlog --to-tag=in-progress`)+`
178
+ `+h.text(` taskgraph move --from=5,6 --from-tag=backlog --to-tag=done`)+`
179
179
 
180
180
  `+B.yellow.bold(`Dependency Resolution:`)+`
181
- `+t.text(` # Move with dependencies`)+`
182
- `+t.text(` taskgraph move --from=5 --from-tag=backlog --to-tag=in-progress --with-dependencies`)+`
181
+ `+h.text(` # Move with dependencies`)+`
182
+ `+h.text(` taskgraph move --from=5 --from-tag=backlog --to-tag=in-progress --with-dependencies`)+`
183
183
 
184
- `+t.text(` # Break dependencies`)+`
185
- `+t.text(` taskgraph move --from=5 --from-tag=backlog --to-tag=in-progress --ignore-dependencies`)+`
184
+ `+h.text(` # Break dependencies`)+`
185
+ `+h.text(` taskgraph move --from=5 --from-tag=backlog --to-tag=in-progress --ignore-dependencies`)+`
186
186
 
187
187
 
188
188
  `+B.yellow.bold(`Best Practices:`)+`
189
- `+t.text(` • Use --with-dependencies to move dependent tasks together`)+`
190
- `+t.text(` • Use --ignore-dependencies to break cross-tag dependencies`)+`
191
- `+t.text(` • Check dependencies first: taskgraph validate-dependencies`)+`
192
- `+t.text(` • Fix dependency issues: taskgraph fix-dependencies`)+`
189
+ `+h.text(` • Use --with-dependencies to move dependent tasks together`)+`
190
+ `+h.text(` • Use --ignore-dependencies to break cross-tag dependencies`)+`
191
+ `+h.text(` • Check dependencies first: taskgraph validate-dependencies`)+`
192
+ `+h.text(` • Fix dependency issues: taskgraph fix-dependencies`)+`
193
193
 
194
194
  `+B.yellow.bold(`Error Resolution:`)+`
195
- `+t.text(` • Cross-tag dependency conflicts: Use --with-dependencies or --ignore-dependencies`)+`
196
- `+t.text(` • Subtask movement: Promote subtask first with remove-subtask --convert`)+`
197
- `+t.text(` • Invalid tags: Check available tags with taskgraph tags`)+`
198
-
199
- `+t.muted(`For more help, run: taskgraph move --help`))}async function r(e,r){let{sourceId:i,sourceTag:a,toTag:o,taskGraph:s}=e;i||(console.error(B.red(`Error: --from parameter is required for cross-tag moves`)),n(),process.exit(1));let c=i.split(`,`).map(e=>e.trim()),l={withDependencies:r.withDependencies||!1,ignoreDependencies:r.ignoreDependencies||!1};console.log(t.brand(`Moving tasks ${c.join(`, `)} from "${a}" to "${o}"...`));let u=await ue(s.getTasksPath(),c,a,o,l,{projectRoot:s.getProjectRoot()});console.log(B.green(`✓ ${u.message}`)),Array.isArray(u.tips)&&u.tips.length>0&&(console.log(`
200
- `+B.yellow.bold(`Next Steps:`)),u.tips.forEach(e=>console.log(t.text(` • ${e}`))))}async function i(e){let{sourceId:n,destinationId:r,tag:i,taskGraph:a}=e;(!n||!r)&&(console.error(B.red(`Error: Both --from and --to parameters are required for within-tag moves`)),console.log(B.yellow(`Usage: taskgraph move --from=<sourceId> --to=<destinationId>`)),process.exit(1));let o=n.split(`,`).map(e=>e.trim()),s=r.split(`,`).map(e=>e.trim());if(o.length!==s.length&&(console.error(B.red(`Error: The number of source and destination IDs must match`)),console.log(B.yellow(`Example: taskgraph move --from=5,6,7 --to=10,11,12`)),process.exit(1)),o.length>1){console.log(t.brand(`Moving multiple tasks: ${o.join(`, `)} to ${s.join(`, `)}...`));let e=p(a.getTasksPath(),a.getProjectRoot(),i);(!e||!e.tasks)&&(console.error(B.red(`Error: Invalid or missing tasks file at ${a.getTasksPath()}`)),process.exit(1));let n=[],r=[];for(let e=0;e<o.length;e++){let c=o[e],l=s[e];if(c===l){console.log(B.yellow(`Skipping ${c} -> ${l} (same ID)`));continue}console.log(t.brand(`Moving task/subtask ${c} to ${l}...`));try{await v(a.getTasksPath(),c,l,e===o.length-1,{projectRoot:a.getProjectRoot(),tag:i}),console.log(B.green(`✓ Successfully moved task/subtask ${c} to ${l}`)),r.push({fromId:c,toId:l})}catch(e){let t={fromId:c,toId:l,error:e.message};n.push(t),console.error(B.red(`Error moving ${c} to ${l}: ${e.message}`))}}n.length>0?(console.log(B.yellow(`
201
- --- Move Operation Summary ---`)),console.log(B.green(`✓ Successfully moved: ${r.length} tasks`)),console.log(B.red(`✗ Failed to move: ${n.length} tasks`)),r.length>0&&(console.log(B.cyan(`
202
- Successful moves:`)),r.forEach(({fromId:e,toId:t})=>{console.log(B.cyan(` ${e} → ${t}`))})),console.log(B.red(`
203
- Failed moves:`)),n.forEach(({fromId:e,toId:t,error:n})=>{console.log(B.red(` ${e} → ${t}: ${n}`))}),console.log(B.yellow(`
195
+ `+h.text(` • Cross-tag dependency conflicts: Use --with-dependencies or --ignore-dependencies`)+`
196
+ `+h.text(` • Subtask movement: Promote subtask first with remove-subtask --convert`)+`
197
+ `+h.text(` • Invalid tags: Check available tags with taskgraph tags`)+`
198
+
199
+ `+h.muted(`For more help, run: taskgraph move --help`))}async function n(e,n){let{sourceId:r,sourceTag:i,toTag:a,taskGraph:o}=e;r||(console.error(B.red(`Error: --from parameter is required for cross-tag moves`)),t(),process.exit(1));let s=r.split(`,`).map(e=>e.trim()),c={withDependencies:n.withDependencies||!1,ignoreDependencies:n.ignoreDependencies||!1};console.log(h.brand(`Moving tasks ${s.join(`, `)} from "${i}" to "${a}"...`));let l=await ue(o.getTasksPath(),s,i,a,c,{projectRoot:o.getProjectRoot()});console.log(B.green(`✓ ${l.message}`)),Array.isArray(l.tips)&&l.tips.length>0&&(console.log(`
200
+ `+B.yellow.bold(`Next Steps:`)),l.tips.forEach(e=>console.log(h.text(` • ${e}`))))}async function r(e){let{sourceId:t,destinationId:n,tag:r,taskGraph:i}=e;(!t||!n)&&(console.error(B.red(`Error: Both --from and --to parameters are required for within-tag moves`)),console.log(B.yellow(`Usage: taskgraph move --from=<sourceId> --to=<destinationId>`)),process.exit(1));let a=t.split(`,`).map(e=>e.trim()),o=n.split(`,`).map(e=>e.trim());if(a.length!==o.length&&(console.error(B.red(`Error: The number of source and destination IDs must match`)),console.log(B.yellow(`Example: taskgraph move --from=5,6,7 --to=10,11,12`)),process.exit(1)),a.length>1){console.log(h.brand(`Moving multiple tasks: ${a.join(`, `)} to ${o.join(`, `)}...`));let e=l(i.getTasksPath(),i.getProjectRoot(),r);(!e||!e.tasks)&&(console.error(B.red(`Error: Invalid or missing tasks file at ${i.getTasksPath()}`)),process.exit(1));let t=[],n=[];for(let e=0;e<a.length;e++){let s=a[e],c=o[e];if(s===c){console.log(B.yellow(`Skipping ${s} -> ${c} (same ID)`));continue}console.log(h.brand(`Moving task/subtask ${s} to ${c}...`));try{await v(i.getTasksPath(),s,c,e===a.length-1,{projectRoot:i.getProjectRoot(),tag:r}),console.log(B.green(`✓ Successfully moved task/subtask ${s} to ${c}`)),n.push({fromId:s,toId:c})}catch(e){let n={fromId:s,toId:c,error:e.message};t.push(n),console.error(B.red(`Error moving ${s} to ${c}: ${e.message}`))}}t.length>0?(console.log(B.yellow(`
201
+ --- Move Operation Summary ---`)),console.log(B.green(`✓ Successfully moved: ${n.length} tasks`)),console.log(B.red(`✗ Failed to move: ${t.length} tasks`)),n.length>0&&(console.log(B.cyan(`
202
+ Successful moves:`)),n.forEach(({fromId:e,toId:t})=>{console.log(B.cyan(` ${e} → ${t}`))})),console.log(B.red(`
203
+ Failed moves:`)),t.forEach(({fromId:e,toId:t,error:n})=>{console.log(B.red(` ${e} → ${t}: ${n}`))}),console.log(B.yellow(`
204
204
  Note: Some tasks were moved successfully. Check the errors above for failed moves.`))):console.log(B.green(`
205
- ✓ All tasks moved successfully!`))}else console.log(t.brand(`Moving task/subtask ${n} to ${r}...`)),await v(a.getTasksPath(),n,r,!0,{projectRoot:a.getProjectRoot(),tag:i}),console.log(B.green(`✓ Successfully moved task/subtask ${n} to ${r}`))}function a(e,t){if(console.error(B.red(`Error: ${e.message}`)),e.code===`CROSS_TAG_DEPENDENCY_CONFLICTS`){let n=e.data.conflicts||[],r=e.data.taskIds||[];Te(n,t.sourceTag,t.toTag,r.join(`, `))}else e.code===`CANNOT_MOVE_SUBTASK`?O(e.data.taskId||t.sourceId?.split(`,`)[0],t.sourceTag,t.toTag):e.code===`SOURCE_TARGET_TAGS_SAME`||e.code===`SAME_SOURCE_TARGET_TAG`?F(t.sourceTag,t.toTag,`Source and target tags are identical`):D(`after-error`);process.exit(1)}let o=X({tasksPath:e.file||!0,tag:e.tag}),s=e.from,c=e.to,l=e.fromTag,u=e.toTag,d=o.getCurrentTag(),f=l||o.getCurrentTag(),m=f&&u&&f!==u,h={sourceId:s,destinationId:c,sourceTag:f,toTag:u,tag:d,taskGraph:o};try{m?await r(h,e):await i(h)}catch(e){let n=String(e&&(e.message||e));n.includes(`already exists in target tag`)&&(console.error(B.red(`Error: ${n}`)),console.log(`
205
+ ✓ All tasks moved successfully!`))}else console.log(h.brand(`Moving task/subtask ${t} to ${n}...`)),await v(i.getTasksPath(),t,n,!0,{projectRoot:i.getProjectRoot(),tag:r}),console.log(B.green(`✓ Successfully moved task/subtask ${t} to ${n}`))}function i(e,t){if(console.error(B.red(`Error: ${e.message}`)),e.code===`CROSS_TAG_DEPENDENCY_CONFLICTS`){let n=e.data.conflicts||[],r=e.data.taskIds||[];Te(n,t.sourceTag,t.toTag,r.join(`, `))}else e.code===`CANNOT_MOVE_SUBTASK`?O(e.data.taskId||t.sourceId?.split(`,`)[0],t.sourceTag,t.toTag):e.code===`SOURCE_TARGET_TAGS_SAME`||e.code===`SAME_SOURCE_TARGET_TAG`?F(t.sourceTag,t.toTag,`Source and target tags are identical`):D(`after-error`);process.exit(1)}let a=X({tasksPath:e.file||!0,tag:e.tag}),o=e.from,s=e.to,c=e.fromTag,u=e.toTag,d=a.getCurrentTag(),f=c||a.getCurrentTag(),p=f&&u&&f!==u,m={sourceId:o,destinationId:s,sourceTag:f,toTag:u,tag:d,taskGraph:a};try{p?await n(m,e):await r(m)}catch(e){let t=String(e&&(e.message||e));t.includes(`already exists in target tag`)&&(console.error(B.red(`Error: ${t}`)),console.log(`
206
206
  `+B.yellow.bold(`Conflict: ID already exists in target tag`)+`
207
- `+t.text(` • Choose a different target tag without conflicting IDs`)+`
208
- `+t.text(` • Move a different set of IDs (avoid existing ones)`)+`
209
- `+t.text(` • If needed, move within-tag to a new ID first, then cross-tag move`)),process.exit(1)),a(e,h)}}),e.command(`sync-readme`).description(`Sync the current task list to README.md in the project root`).option(`-f, --file <file>`,`Path to the tasks file`,r).option(`--with-subtasks`,`Include subtasks in the README output`).option(`-s, --status <status>`,`Show only tasks matching this status (e.g., pending, done)`).option(`-t, --tag <tag>`,`Tag to use for the task list (default: master)`).action(async e=>{let n=X({tasksPath:e.file||!0,tag:e.tag}),r=e.withSubtasks||!1,i=e.status||null,a=n.getCurrentTag();console.log(t.brand(`📝 Syncing tasks to README.md${r?` (with subtasks)`:``}${i?` (status: ${i})`:``}...`)),await syncTasksToReadme(n.getProjectRoot(),{withSubtasks:r,status:i,tasksPath:n.getTasksPath(),tag:a})||(console.error(B.red(`❌ Failed to sync tasks to README.md`)),process.exit(1))}),e.command(`add-tag`).description(`[DEPRECATED] Create a new tag context for organizing tasks (use "tm tags add" instead)`).argument(`[tagName]`,`Name of the new tag to create (optional when using --from-branch)`).option(`-f, --file <file>`,`Path to the tasks file`,r).option(`--copy-from-current`,`Copy tasks from the current tag to the new tag`).option(`--copy-from <tag>`,`Copy tasks from the specified tag to the new tag`).option(`--from-branch`,`Create tag name from current git branch (ignores tagName argument)`).option(`-d, --description <text>`,`Optional description for the tag`).action(async(e,n)=>{console.warn(B.yellow(`⚠ Warning: "tm add-tag" is deprecated. Use "tm tags add" instead.`)),console.log(t.muted(` This command will be removed in a future version.
210
- `));try{let t=X({tasksPath:n.file||!0}),r=t.getTasksPath();V.existsSync(r)||(console.error(B.red(`Error: Tasks file not found at path: ${r}`)),console.log(B.yellow(`Hint: Run taskgraph init or taskgraph parse-prd to create tasks.json first`)),process.exit(1)),!e&&!n.fromBranch&&(console.error(B.red(`Error: Either tagName argument or --from-branch option is required.`)),console.log(B.yellow(`Usage examples:`)),console.log(B.cyan(` taskgraph add-tag my-tag`)),console.log(B.cyan(` taskgraph add-tag --from-branch`)),process.exit(1));let i={projectRoot:t.getProjectRoot(),commandName:`add-tag`,outputType:`cli`};if(n.fromBranch){let{createTagFromBranch:e}=await import(`./tag-management-BEKnBGXA.js`),r=await import(`./git-utils-PBP1PRVP.js`);await r.isGitRepository(i.projectRoot)||(console.error(B.red(`Error: Not in a git repository. Cannot use --from-branch option.`)),process.exit(1));let a=await r.getCurrentBranch(i.projectRoot);a||(console.error(B.red(`Error: Could not determine current git branch.`)),process.exit(1));let o={copyFromCurrent:n.copyFromCurrent||!1,copyFromTag:n.copyFrom,description:n.description||`Tag created from git branch "${a}"`};await e(t.getTasksPath(),a,o,i,`text`)}else{let r={copyFromCurrent:n.copyFromCurrent||!1,copyFromTag:n.copyFrom,description:n.description};await ge(t.getTasksPath(),e,r,i,`text`)}if(n.autoSwitch){let{useTag:r}=await import(`./tag-management-BEKnBGXA.js`),a=n.fromBranch?(await import(`./git-utils-PBP1PRVP.js`)).sanitizeBranchNameForTag(await(await import(`./git-utils-PBP1PRVP.js`)).getCurrentBranch(projectRoot)):e;await r(t.getTasksPath(),a,{},i,`text`)}}catch(e){console.error(B.red(`Error creating tag: ${e.message}`)),l(),process.exit(1)}}).on(`error`,function(e){console.error(B.red(`Error: ${e.message}`)),l(),process.exit(1)}),e.command(`delete-tag`).description(`[DEPRECATED] Delete an existing tag and all its tasks (use "tm tags remove" instead)`).argument(`<tagName>`,`Name of the tag to delete`).option(`-f, --file <file>`,`Path to the tasks file`,r).option(`-y, --yes`,`Skip confirmation prompts`).action(async(e,n)=>{console.warn(B.yellow(`⚠ Warning: "tm delete-tag" is deprecated. Use "tm tags remove" instead.`)),console.log(t.muted(` This command will be removed in a future version.
211
- `));try{let t=X({tasksPath:n.file||!0}),r=t.getTasksPath();V.existsSync(r)||(console.error(B.red(`Error: Tasks file not found at path: ${r}`)),process.exit(1));let i={yes:n.yes||!1},a={projectRoot:t.getProjectRoot(),commandName:`delete-tag`,outputType:`cli`};await ee(t.getTasksPath(),e,i,a,`text`)}catch(e){console.error(B.red(`Error deleting tag: ${e.message}`)),u(),process.exit(1)}}).on(`error`,function(e){console.error(B.red(`Error: ${e.message}`)),u(),process.exit(1)}),e.command(`use-tag`).description(`[DEPRECATED] Switch to a different tag context (use "tm tags use" instead)`).argument(`<tagName>`,`Name of the tag to switch to`).option(`-f, --file <file>`,`Path to the tasks file`,r).action(async(e,n)=>{console.warn(B.yellow(`⚠ Warning: "tm use-tag" is deprecated. Use "tm tags use" instead.`)),console.log(t.muted(` This command will be removed in a future version.
212
- `));try{let t=X({tasksPath:n.file||!0}),r=t.getTasksPath();V.existsSync(r)||(console.error(B.red(`Error: Tasks file not found at path: ${r}`)),process.exit(1));let i={projectRoot:t.getProjectRoot(),commandName:`use-tag`,outputType:`cli`};await j(t.getTasksPath(),e,{},i,`text`)}catch(e){console.error(B.red(`Error switching tag: ${e.message}`)),f(),process.exit(1)}}).on(`error`,function(e){console.error(B.red(`Error: ${e.message}`)),f(),process.exit(1)}),e.command(`rename-tag`).description(`[DEPRECATED] Rename an existing tag (use "tm tags rename" instead)`).argument(`<oldName>`,`Current name of the tag`).argument(`<newName>`,`New name for the tag`).option(`-f, --file <file>`,`Path to the tasks file`,r).action(async(e,n,r)=>{console.warn(B.yellow(`⚠ Warning: "tm rename-tag" is deprecated. Use "tm tags rename" instead.`)),console.log(t.muted(` This command will be removed in a future version.
213
- `));try{let t=X({tasksPath:r.file||!0}),i=t.getTasksPath();V.existsSync(i)||(console.error(B.red(`Error: Tasks file not found at path: ${i}`)),process.exit(1));let a={projectRoot:t.getProjectRoot(),commandName:`rename-tag`,outputType:`cli`};await E(t.getTasksPath(),e,n,{},a,`text`)}catch(e){console.error(B.red(`Error renaming tag: ${e.message}`)),process.exit(1)}}).on(`error`,function(e){console.error(B.red(`Error: ${e.message}`)),process.exit(1)}),e.command(`copy-tag`).description(`[DEPRECATED] Copy an existing tag to create a new tag with the same tasks (use "tm tags copy" instead)`).argument(`<sourceName>`,`Name of the source tag to copy from`).argument(`<targetName>`,`Name of the new tag to create`).option(`-f, --file <file>`,`Path to the tasks file`,r).option(`-d, --description <text>`,`Optional description for the new tag`).action(async(e,n,r)=>{console.warn(B.yellow(`⚠ Warning: "tm copy-tag" is deprecated. Use "tm tags copy" instead.`)),console.log(t.muted(` This command will be removed in a future version.
214
- `));try{let t=X({tasksPath:r.file||!0}),i=t.getTasksPath();V.existsSync(i)||(console.error(B.red(`Error: Tasks file not found at path: ${i}`)),process.exit(1)),await me(i,e,n,{description:r.description},{projectRoot:t.getProjectRoot(),commandName:`copy-tag`,outputType:`cli`},`text`)}catch(e){console.error(B.red(`Error copying tag: ${e.message}`)),process.exit(1)}}).on(`error`,function(e){console.error(B.red(`Error: ${e.message}`)),process.exit(1)}),e.command(`tui`).alias(`repl`).description(`Launch the interactive TUI/REPL mode`).action(async()=>{await Q()}),e}async function ze(){return null}async function Q(){let e=await ze();if(!e){console.log(B.yellow(`TUI mode coming soon!`)),console.log(B.dim(`Showing help instead...
207
+ `+h.text(` • Choose a different target tag without conflicting IDs`)+`
208
+ `+h.text(` • Move a different set of IDs (avoid existing ones)`)+`
209
+ `+h.text(` • If needed, move within-tag to a new ID first, then cross-tag move`)),process.exit(1)),i(e,m)}}),e.command(`sync-readme`).description(`Sync the current task list to README.md in the project root`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`--with-subtasks`,`Include subtasks in the README output`).option(`-s, --status <status>`,`Show only tasks matching this status (e.g., pending, done)`).option(`-t, --tag <tag>`,`Tag to use for the task list (default: master)`).action(async e=>{let t=X({tasksPath:e.file||!0,tag:e.tag}),n=e.withSubtasks||!1,r=e.status||null,i=t.getCurrentTag();console.log(h.brand(`📝 Syncing tasks to README.md${n?` (with subtasks)`:``}${r?` (status: ${r})`:``}...`)),await syncTasksToReadme(t.getProjectRoot(),{withSubtasks:n,status:r,tasksPath:t.getTasksPath(),tag:i})||(console.error(B.red(`❌ Failed to sync tasks to README.md`)),process.exit(1))}),e.command(`add-tag`).description(`[DEPRECATED] Create a new tag context for organizing tasks (use "tm tags add" instead)`).argument(`[tagName]`,`Name of the new tag to create (optional when using --from-branch)`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`--copy-from-current`,`Copy tasks from the current tag to the new tag`).option(`--copy-from <tag>`,`Copy tasks from the specified tag to the new tag`).option(`--from-branch`,`Create tag name from current git branch (ignores tagName argument)`).option(`-d, --description <text>`,`Optional description for the tag`).action(async(e,t)=>{console.warn(B.yellow(`⚠ Warning: "tm add-tag" is deprecated. Use "tm tags add" instead.`)),console.log(h.muted(` This command will be removed in a future version.
210
+ `));try{let n=X({tasksPath:t.file||!0}),r=n.getTasksPath();H.existsSync(r)||(console.error(B.red(`Error: Tasks file not found at path: ${r}`)),console.log(B.yellow(`Hint: Run taskgraph init or taskgraph parse-prd to create tasks.json first`)),process.exit(1)),!e&&!t.fromBranch&&(console.error(B.red(`Error: Either tagName argument or --from-branch option is required.`)),console.log(B.yellow(`Usage examples:`)),console.log(B.cyan(` taskgraph add-tag my-tag`)),console.log(B.cyan(` taskgraph add-tag --from-branch`)),process.exit(1));let i={projectRoot:n.getProjectRoot(),commandName:`add-tag`,outputType:`cli`};if(t.fromBranch){let{createTagFromBranch:e}=await import(`./tag-management-Du0gQ3h8.js`),r=await import(`./git-utils-BFUgMf2g.js`);await r.isGitRepository(i.projectRoot)||(console.error(B.red(`Error: Not in a git repository. Cannot use --from-branch option.`)),process.exit(1));let a=await r.getCurrentBranch(i.projectRoot);a||(console.error(B.red(`Error: Could not determine current git branch.`)),process.exit(1));let o={copyFromCurrent:t.copyFromCurrent||!1,copyFromTag:t.copyFrom,description:t.description||`Tag created from git branch "${a}"`};await e(n.getTasksPath(),a,o,i,`text`)}else{let r={copyFromCurrent:t.copyFromCurrent||!1,copyFromTag:t.copyFrom,description:t.description};await ge(n.getTasksPath(),e,r,i,`text`)}if(t.autoSwitch){let{useTag:r}=await import(`./tag-management-Du0gQ3h8.js`),a=t.fromBranch?(await import(`./git-utils-BFUgMf2g.js`)).sanitizeBranchNameForTag(await(await import(`./git-utils-BFUgMf2g.js`)).getCurrentBranch(projectRoot)):e;await r(n.getTasksPath(),a,{},i,`text`)}}catch(e){console.error(B.red(`Error creating tag: ${e.message}`)),a(),process.exit(1)}}).on(`error`,function(e){console.error(B.red(`Error: ${e.message}`)),a(),process.exit(1)}),e.command(`delete-tag`).description(`[DEPRECATED] Delete an existing tag and all its tasks (use "tm tags remove" instead)`).argument(`<tagName>`,`Name of the tag to delete`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`-y, --yes`,`Skip confirmation prompts`).action(async(e,t)=>{console.warn(B.yellow(`⚠ Warning: "tm delete-tag" is deprecated. Use "tm tags remove" instead.`)),console.log(h.muted(` This command will be removed in a future version.
211
+ `));try{let n=X({tasksPath:t.file||!0}),r=n.getTasksPath();H.existsSync(r)||(console.error(B.red(`Error: Tasks file not found at path: ${r}`)),process.exit(1));let i={yes:t.yes||!1},a={projectRoot:n.getProjectRoot(),commandName:`delete-tag`,outputType:`cli`};await ee(n.getTasksPath(),e,i,a,`text`)}catch(e){console.error(B.red(`Error deleting tag: ${e.message}`)),u(),process.exit(1)}}).on(`error`,function(e){console.error(B.red(`Error: ${e.message}`)),u(),process.exit(1)}),e.command(`use-tag`).description(`[DEPRECATED] Switch to a different tag context (use "tm tags use" instead)`).argument(`<tagName>`,`Name of the tag to switch to`).option(`-f, --file <file>`,`Path to the tasks file`,i).action(async(e,t)=>{console.warn(B.yellow(`⚠ Warning: "tm use-tag" is deprecated. Use "tm tags use" instead.`)),console.log(h.muted(` This command will be removed in a future version.
212
+ `));try{let n=X({tasksPath:t.file||!0}),r=n.getTasksPath();H.existsSync(r)||(console.error(B.red(`Error: Tasks file not found at path: ${r}`)),process.exit(1));let i={projectRoot:n.getProjectRoot(),commandName:`use-tag`,outputType:`cli`};await j(n.getTasksPath(),e,{},i,`text`)}catch(e){console.error(B.red(`Error switching tag: ${e.message}`)),m(),process.exit(1)}}).on(`error`,function(e){console.error(B.red(`Error: ${e.message}`)),m(),process.exit(1)}),e.command(`rename-tag`).description(`[DEPRECATED] Rename an existing tag (use "tm tags rename" instead)`).argument(`<oldName>`,`Current name of the tag`).argument(`<newName>`,`New name for the tag`).option(`-f, --file <file>`,`Path to the tasks file`,i).action(async(e,t,n)=>{console.warn(B.yellow(`⚠ Warning: "tm rename-tag" is deprecated. Use "tm tags rename" instead.`)),console.log(h.muted(` This command will be removed in a future version.
213
+ `));try{let r=X({tasksPath:n.file||!0}),i=r.getTasksPath();H.existsSync(i)||(console.error(B.red(`Error: Tasks file not found at path: ${i}`)),process.exit(1));let a={projectRoot:r.getProjectRoot(),commandName:`rename-tag`,outputType:`cli`};await E(r.getTasksPath(),e,t,{},a,`text`)}catch(e){console.error(B.red(`Error renaming tag: ${e.message}`)),process.exit(1)}}).on(`error`,function(e){console.error(B.red(`Error: ${e.message}`)),process.exit(1)}),e.command(`copy-tag`).description(`[DEPRECATED] Copy an existing tag to create a new tag with the same tasks (use "tm tags copy" instead)`).argument(`<sourceName>`,`Name of the source tag to copy from`).argument(`<targetName>`,`Name of the new tag to create`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`-d, --description <text>`,`Optional description for the new tag`).action(async(e,t,n)=>{console.warn(B.yellow(`⚠ Warning: "tm copy-tag" is deprecated. Use "tm tags copy" instead.`)),console.log(h.muted(` This command will be removed in a future version.
214
+ `));try{let r=X({tasksPath:n.file||!0}),i=r.getTasksPath();H.existsSync(i)||(console.error(B.red(`Error: Tasks file not found at path: ${i}`)),process.exit(1)),await me(i,e,t,{description:n.description},{projectRoot:r.getProjectRoot(),commandName:`copy-tag`,outputType:`cli`},`text`)}catch(e){console.error(B.red(`Error copying tag: ${e.message}`)),process.exit(1)}}).on(`error`,function(e){console.error(B.red(`Error: ${e.message}`)),process.exit(1)}),e.command(`tui`).alias(`repl`).description(`Launch the interactive TUI/REPL mode`).action(async()=>{await Q()}),e}async function ze(){return null}async function Q(){let e=await ze();if(!e){console.log(B.yellow(`TUI mode coming soon!`)),console.log(B.dim(`Showing help instead...
215
215
  `)),L();return}let t=await import(`react`),{render:n,Shell:r}=e,i=`master`,a=process.cwd();try{let e=X({});i=e.getCurrentTag(),a=e.getProjectRoot()||process.cwd()}catch{}let o=process.stdin.isTTY&&typeof process.stdin.setRawMode==`function`;console.clear();let s={showBanner:!0,showSplash:o,initialTag:i,isInteractive:o,projectRoot:a,onExit:()=>{console.log(B.dim(`
216
216
  Goodbye! 👋`)),process.exit(0)}},c=n(t.createElement(r,s));o||setTimeout(()=>{c.unmount(),console.log(B.dim(`
217
- 💡 Run in an interactive terminal for full REPL mode.`)),process.exit(0)},200)}function $(){let e=new Ne().name(`taskgraph`).description(`AI-driven development task management`).version(`0.49.1`).helpOption(`-h, --help`,`Display help`).addHelpCommand(!1),t=e.helpInformation.bind(e);return e.helpInformation=function(){return this.parent&&this.parent!==e?t():(L(),``)},Z(e),e}async function Be(e=process.argv){try{if(e.length<=2){await Q();return}let t=e.includes(`init`),n=e.includes(`tui`)||e.includes(`repl`),r=e.includes(`--no-banner`);process.stdout.isTTY&&!t&&!n&&!r&&Se();let i=process.env.TASKGRAPH_SKIP_AUTO_UPDATE===`1`||process.env.CI||process.env.NODE_ENV===`test`,a=x(),o=i?{currentVersion:a,latestVersion:a,needsUpdate:!1}:await P(a);if(o.needsUpdate&&(w(o.currentVersion,o.latestVersion,o.highlights),await Ce(o.latestVersion))){ye(e);return}let s=$(),c=e.filter(e=>e!==`--no-banner`);await s.parseAsync(c);try{let e=X({}),t=e.getTasksPath(),n=e.getStatePath();if(t&&V.existsSync(t)){let e=V.readFileSync(t,`utf8`),r=JSON.parse(e);if(r&&r.master){let e={migrationNoticeShown:!1};if(n&&V.existsSync(n)){let t=V.readFileSync(n,`utf8`);e=JSON.parse(t)||e}e.migrationNoticeShown||(_e({_migrationHappened:!0}),e.migrationNoticeShown=!0,n&&V.writeFileSync(n,JSON.stringify(e,null,2)))}}}catch{}}catch(e){e instanceof f?console.error(U(B.red.bold(`Configuration Update Required!`)+`
217
+ 💡 Run in an interactive terminal for full REPL mode.`)),process.exit(0)},200)}function $(){let e=new Ne().name(`taskgraph`).description(`AI-driven development task management`).version(`0.52.2`).helpOption(`-h, --help`,`Display help`).addHelpCommand(!1),t=e.helpInformation.bind(e);return e.helpInformation=function(){return this.parent&&this.parent!==e?t():(L(),``)},Z(e),e}async function Be(e=process.argv){try{if(e.length<=2){await Q();return}let t=e.includes(`init`),n=e.includes(`tui`)||e.includes(`repl`),r=e.includes(`--no-banner`);process.stdout.isTTY&&!t&&!n&&!r&&Se();let i=process.env.TASKGRAPH_SKIP_AUTO_UPDATE===`1`||process.env.CI||process.env.NODE_ENV===`test`,a=x(),o=i?{currentVersion:a,latestVersion:a,needsUpdate:!1}:await P(a);if(o.needsUpdate&&(w(o.currentVersion,o.latestVersion,o.highlights),await Ce(o.latestVersion))){ye(e);return}let s=$(),c=e.filter(e=>e!==`--no-banner`);await s.parseAsync(c);try{let e=X({}),t=e.getTasksPath(),n=e.getStatePath();if(t&&H.existsSync(t)){let e=H.readFileSync(t,`utf8`),r=JSON.parse(e);if(r&&r.master){let e={migrationNoticeShown:!1};if(n&&H.existsSync(n)){let t=H.readFileSync(n,`utf8`);e=JSON.parse(t)||e}e.migrationNoticeShown||(_e({_migrationHappened:!0}),e.migrationNoticeShown=!0,n&&H.writeFileSync(n,JSON.stringify(e,null,2)))}}}catch{}}catch(e){e instanceof m?console.error(U(B.red.bold(`Configuration Update Required!`)+`
218
218
 
219
- `+t.text(`TaskGraph now uses a `)+B.yellow.bold(`configuration file`)+t.text(` in your project for AI model choices and settings.
219
+ `+h.text(`TaskGraph now uses a `)+B.yellow.bold(`configuration file`)+h.text(` in your project for AI model choices and settings.
220
220
 
221
- This file appears to be `)+B.red.bold(`missing`)+t.text(`. No worries though.
221
+ This file appears to be `)+B.red.bold(`missing`)+h.text(`. No worries though.
222
222
 
223
223
  `)+B.cyan.bold(`To create this file, run the interactive setup:`)+`
224
224
  `+B.green(` taskgraph models --setup`)+`
225
225
 
226
- `+t.text.bold(`Key Points:`)+`
227
- `+t.text(`* `)+B.yellow.bold(`Configuration file`)+t.text(`: Stores your AI model settings (do not manually edit)
228
- `)+t.text(`* `)+B.yellow.bold(`.env & .mcp.json`)+t.text(`: Still used `)+B.red.bold(`only`)+t.text(` for your AI provider API keys.
226
+ `+h.text.bold(`Key Points:`)+`
227
+ `+h.text(`* `)+B.yellow.bold(`Configuration file`)+h.text(`: Stores your AI model settings (do not manually edit)
228
+ `)+h.text(`* `)+B.yellow.bold(`.env & .mcp.json`)+h.text(`: Still used `)+B.red.bold(`only`)+h.text(` for your AI provider API keys.
229
229
 
230
230
  `)+B.cyan("`taskgraph models` to check your config & available models\n")+B.cyan("`taskgraph models --setup` to adjust the AI models used by TaskGraph"),{padding:1,margin:{top:1},borderColor:`red`,borderStyle:`round`})):Ee(e),process.exit(1)}}export{Q as launchREPL,Z as registerCommands,Be as runCLI,$ as setupCLI};