taskgraph-ai 0.54.14 → 0.54.22

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.
@@ -1 +0,0 @@
1
- export{c as createTagFromBranch,m as useTag}from"./src-Dz_uZuYA.js";
@@ -1,167 +0,0 @@
1
- import{A as e,_ as t,b as n,d as r,g as i,h as a,k as o,m as s,p as c,v as l,y as u}from"./src-DvvdBXWU.js";import{$ as d,B as f,C as p,G as m,J as h,K as g,N as _,Q as v,V as y,W as b,X as x,Y as S,_t as C,c as w,ct as T,dt as E,et as D,g as O,gt as k,h as A,ht as j,it as M,l as N,lt as P,nt as ee,o as F,p as I,pt as L,q as te,rt as ne,st as re,tt as ie,u as ae,v as oe,z as se}from"./config-manager-CtE1yo1I.js";import{B as R,C as ce,U as le,h as ue}from"./src-Dz_uZuYA.js";import{A as z,C as B,S as de,_ as fe,a as pe,b as V,d as H,f as me,g as he,i as ge,k as _e,r as ve,u as ye,v as be,w as xe,x as U,y as Se}from"./research-DcB3PdqA.js";import{i as Ce,n as we,r as Te,t as W}from"./ai-services-unified-CvcPXr89.js";import"./response-language-BdYSHT6o.js";import G from"chalk";import Ee from"path";import{z as K}from"zod";import q,*as De from"fs";import J from"boxen";import Oe from"cli-table3";import"fuse.js";import{APICallError as ke}from"ai";import"@streamparser/json";import Ae from"cli-progress";function je(n,r,i){let o=t=>r===void 0?String(t):e(r,t),s=i===void 0?void 0:String(i),c=[...new Set((n.dependencies??[]).map(o))].filter(e=>e!==s),l=t(n,r,s,o);return{dependencies:c,metadata:a({dependencies:c,metadata:l},s)}}function Me(e,t){return je(e,void 0,t)}function Ne(t,n,r){let i=(e,t,r,i)=>{e.dependencies?.some(e=>t(e)===n)&&(e.dependencies=e.dependencies.map(e=>t(e)===n?r:e),c(e,l(e.metadata,n,String(r),i)))};for(let n of t){i(n,String,r);for(let t of n.subtasks??[])i(t,t=>e(n.id,t),String(r),n.id)}}const Pe="Run `taskgraph list` to see task IDs",Fe="Create some with `taskgraph parse-prd <file>`";function Ie(e,t,n,r){c(e,u(e.metadata,t,n,r))}function Le(e){for(let t of e||[]){t.metadata&&c(t,a(t));for(let e of t.subtasks||[])e.metadata&&c(e,a(e,t.id))}}var Re=class extends Error{constructor(e,t,n={},r){super(t,r),this.name=`DependencyError`,this.code=e,this.data=n}};const Y={NO_TASKS:`NO_TASKS`,TASK_NOT_FOUND:`TASK_NOT_FOUND`,NO_SUBTASKS:`NO_SUBTASKS`,SELF_DEPENDENCY:`SELF_DEPENDENCY`,CIRCULAR_DEPENDENCY:`CIRCULAR_DEPENDENCY`,FIX_FAILED:`FIX_FAILED`,CANNOT_MOVE_SUBTASK:`CANNOT_MOVE_SUBTASK`,INVALID_TASK_ID:`INVALID_TASK_ID`,INVALID_SOURCE_TAG:`INVALID_SOURCE_TAG`,INVALID_TARGET_TAG:`INVALID_TARGET_TAG`};function X(e,t,n,r){return new Re(e,t,{hint:n},r&&{cause:r})}async function ze(e,t,n,r={}){d(`debug`,`Adding dependency ${n} to task ${t}...`);let i=M(e,r.projectRoot,r.tag);if(!i||!i.tasks)throw X(Y.NO_TASKS,`No tasks yet`,Fe);let a=typeof t==`string`&&t.includes(`.`)?t:parseInt(t,10),o=S(n);if(!re(i.tasks,o))throw X(Y.TASK_NOT_FOUND,`Task ${o} not found`,Pe);let c=null,l;if(typeof a==`string`&&a.includes(`.`)){let[e,t]=a.split(`.`).map(e=>parseInt(e,10)),n=i.tasks.find(t=>t.id===e);if(!n)throw X(Y.TASK_NOT_FOUND,`Task ${e} not found`,Pe);if(!n.subtasks)throw X(Y.NO_SUBTASKS,`Task ${e} has no subtasks`,`Add some with \`taskgraph expand --id=${e}\``);if(c=n.subtasks.find(e=>e.id===t),l=e,!c)throw X(Y.TASK_NOT_FOUND,`Subtask ${a} not found`,Pe)}else if(c=i.tasks.find(e=>e.id===a),!c)throw X(Y.TASK_NOT_FOUND,`Task ${a} not found`,Pe);if(c.dependencies||(c.dependencies=[]),s(c,o,l)){let t=JSON.stringify(c.metadata);if(Ie(c,o,`explicit`,l),JSON.stringify(c.metadata)!==t){E(e,i,r.projectRoot,r.tag),d(`success`,`Task ${a} now lists task ${o} as an explicit dependency`);return}d(`info`,`Task ${a} already depends on task ${o}; nothing changed`);return}if(String(a)===String(o))throw X(Y.SELF_DEPENDENCY,`Task ${a} can't depend on itself`);let u=!1;if(typeof a==`string`&&typeof o==`string`&&a.includes(`.`)&&o.includes(`.`)){let[e]=a.split(`.`),[t]=o.split(`.`);u=a===o,d(`debug`,`Adding dependency between subtasks: ${a} depends on ${o}`),d(`debug`,`Parent IDs: ${e} and ${t}, Self-dependency check: ${u}`)}if(u)throw X(Y.SELF_DEPENDENCY,`Subtask ${a} can't depend on itself`);let f=[a];if(!Ve(i.tasks,o,f))c.dependencies.push(o),Ie(c,o,`explicit`,l),c.dependencies.sort((e,t)=>{if(typeof e==`number`&&typeof t==`number`)return e-t;if(typeof e==`string`&&typeof t==`string`){let[n,r]=e.split(`.`).map(Number),[i,a]=t.split(`.`).map(Number);return n===i?r-a:n-i}return typeof e==`number`?-1:1}),E(e,i,r.projectRoot,r.tag),d(`success`,`Task ${a} now depends on task ${o}`),d(`debug`,`Task files regenerated with updated dependencies.`);else throw X(Y.CIRCULAR_DEPENDENCY,`That would make a loop: task ${o} already depends on task ${a}`,"Run `taskgraph graph` to see how they connect")}async function Be(t,n,r,i={}){d(`debug`,`Removing dependency ${r} from task ${n}...`);let a=M(t,i.projectRoot,i.tag);if(!a||!a.tasks)throw X(Y.NO_TASKS,`No tasks yet`,Fe);let o=typeof n==`string`&&n.includes(`.`)?n:parseInt(n,10),s=S(r),c=null,l=!1;if(typeof o==`string`&&o.includes(`.`)){let[e,t]=o.split(`.`).map(e=>parseInt(e,10)),n=a.tasks.find(t=>t.id===e);if(!n)throw X(Y.TASK_NOT_FOUND,`Task ${e} not found`,Pe);if(!n.subtasks)throw X(Y.NO_SUBTASKS,`Task ${e} has no subtasks`,`Add some with \`taskgraph expand --id=${e}\``);if(c=n.subtasks.find(e=>e.id===t),l=!0,!c)throw X(Y.TASK_NOT_FOUND,`Subtask ${o} not found`,Pe)}else if(c=a.tasks.find(e=>e.id===o),!c)throw X(Y.TASK_NOT_FOUND,`Task ${o} not found`,Pe);if(!c.dependencies||c.dependencies.length===0){d(`info`,`Task ${o} has no dependencies; nothing changed`);return}let u=String(s),f=c.dependencies.findIndex(t=>(l?e(o.split(`.`)[0],t):String(t))===u);if(f===-1){d(`info`,`Task ${o} doesn't depend on task ${s}; nothing changed`);return}let[p]=c.dependencies.splice(f,1);Ie(c,p,`explicit`,l?o.split(`.`)[0]:void 0),E(t,a,i.projectRoot,i.tag),d(`success`,`Task ${o} no longer depends on task ${s}`)}function Ve(t,n,r=[]){let i=String(n);if(r.some(e=>String(e)===i))return!0;let a=null,o=null;if(i.includes(`.`)){let[e,n]=i.split(`.`).map(Number),r=t.find(t=>t.id===e);o=e,r&&r.subtasks&&(a=r.subtasks.find(e=>e.id===n))}else{let e=parseInt(i,10);a=t.find(t=>t.id===e||String(t.id)===i)}if(!a||!a.dependencies||a.dependencies.length===0)return!1;let s=[...r,i];return a.dependencies.some(n=>Ve(t,o===null?String(n):e(o,n),s))}function He(t,{subtasksOnly:n=!1}={}){let r=/* @__PURE__ */ new Map,i=(e,t)=>{let i=t.filter(t=>t!==e&&(!n||t.includes(`.`)));r.set(e,i)};for(let r of t){let t=String(r.id);n||i(t,(r.dependencies||[]).map(String));for(let n of r.subtasks||[])i(`${t}.${n.id}`,(n.dependencies||[]).map(n=>e(t,n)))}return r}function Ue(e){let t=/* @__PURE__ */ new Map,n=/* @__PURE__ */ new Map,r=/* @__PURE__ */ new Set,i=[],a=/* @__PURE__ */ new Set,o=0,s=a=>(t.set(a,o),n.set(a,o),o++,i.push(a),r.add(a),{id:a,edges:e.get(a),next:0});for(let o of e.keys()){if(t.has(o))continue;let c=[s(o)];for(;c.length>0;){let o=c[c.length-1];if(o.next<o.edges.length){let i=o.edges[o.next++];if(i===o.id&&a.add(i),!e.has(i))continue;t.has(i)?r.has(i)&&n.set(o.id,Math.min(n.get(o.id),t.get(i))):c.push(s(i));continue}if(c.pop(),n.get(o.id)===t.get(o.id)){let e=[],t;do t=i.pop(),r.delete(t),e.push(t);while(t!==o.id);if(e.length>1)for(let t of e)a.add(t)}let l=c[c.length-1];l&&n.set(l.id,Math.min(n.get(l.id),n.get(o.id)))}}return a}function We(e){let t=/* @__PURE__ */ new Map;for(let n of e)t.has(n.id)||t.set(n.id,n.subtasks?new Set(n.subtasks.map(e=>e.id)):null);return e=>{if(!e)return!1;if(typeof e==`string`&&e.includes(`.`)){let[n,r]=e.split(`.`).map(e=>parseInt(e,10));return Number.isNaN(n)||Number.isNaN(r)?!1:t.get(n)?.has(r)??!1}let n=parseInt(e,10);return!Number.isNaN(n)&&t.has(n)}}function Ge(t){let n=[],r=Ue(He(t)),i=Ue(He(t,{subtasksOnly:!0})),a=We(t);return t.forEach(t=>{t.dependencies&&(t.dependencies.forEach(e=>{String(e)===String(t.id)?n.push({type:`self`,taskId:t.id,message:`Task ${t.id} depends on itself`}):a(e)||n.push({type:`missing`,taskId:t.id,dependencyId:e,message:`Task ${t.id} depends on non-existent task ${e}`})}),r.has(String(t.id))&&n.push({type:`circular`,taskId:t.id,fixable:!1,message:`Task ${t.id} is part of a circular dependency chain`}),t.subtasks&&t.subtasks.length>0&&t.subtasks.forEach(s=>{if(!s.dependencies)return;let c=`${t.id}.${s.id}`;s.dependencies.forEach(r=>{if(String(r)===String(c)||o(r)&&r===s.id){n.push({type:`self`,taskId:c,message:`Subtask ${c} depends on itself`});return}let i=o(r)?e(t.id,r):r;a(i)||n.push({type:`missing`,taskId:c,dependencyId:i,message:`Subtask ${c} depends on non-existent task/subtask ${r}`})}),r.has(c)&&n.push({type:`circular`,taskId:c,fixable:i.has(c),message:`Subtask ${c} is part of a circular dependency chain`})}))}),{valid:n.length===0,issues:n}}async function Ke(e,t={}){let{context:n={}}=t;d(`debug`,`Checking for invalid dependencies in task files...`);let r=M(e,n.projectRoot,n.tag);if(!r||!r.tasks)throw X(Y.NO_TASKS,`No tasks yet`,Fe);let i=qe(r.tasks);d(`debug`,`Analyzing dependencies for ${i.taskCount} tasks and ${i.subtaskCount} subtasks...`);let{valid:a,issues:o}=Ge(r.tasks);return{valid:a,issues:o,...i}}function qe(e){let t=e.reduce((e,t)=>e+(Array.isArray(t.subtasks)?t.subtasks.length:0),0);return{taskCount:e.length,subtaskCount:t,dependencyCount:Je(e)}}function Je(e){let t=0;return e.forEach(e=>{e.dependencies&&Array.isArray(e.dependencies)&&(t+=e.dependencies.length),e.subtasks&&Array.isArray(e.subtasks)&&e.subtasks.forEach(e=>{e.dependencies&&Array.isArray(e.dependencies)&&(t+=e.dependencies.length)})}),t}async function Ye(t,n={}){let{context:r={}}=n;d(`debug`,`Checking for and fixing invalid dependencies in tasks.json...`);let i=M(t,r.projectRoot,r.tag);if(!i||!i.tasks)throw X(Y.NO_TASKS,`No tasks yet`,Fe);try{let n=[],a=JSON.parse(JSON.stringify(i)),s={nonExistentDependenciesRemoved:0,selfDependenciesRemoved:0,duplicateDependenciesRemoved:0,circularDependenciesFixed:0,tasksFixed:0,subtasksFixed:0};i.tasks.forEach(t=>{if(t.dependencies&&Array.isArray(t.dependencies)){let e=/* @__PURE__ */ new Set,r=t.dependencies.length;t.dependencies=t.dependencies.filter(r=>{let i=String(r);return e.has(i)?(n.push({type:`duplicate`,taskId:t.id,dependencyId:r}),s.duplicateDependenciesRemoved++,!1):(e.add(i),!0)}),t.dependencies.length<r&&s.tasksFixed++}t.subtasks&&Array.isArray(t.subtasks)&&t.subtasks.forEach(r=>{if(r.dependencies&&Array.isArray(r.dependencies)){let i=/* @__PURE__ */ new Set,a=r.dependencies.length;r.dependencies=r.dependencies.filter(a=>{let o=e(t.id,a);return i.has(o)?(n.push({type:`duplicate`,taskId:`${t.id}.${r.id}`,dependencyId:o}),s.duplicateDependenciesRemoved++,!1):(i.add(o),!0)}),r.dependencies.length<a&&s.subtasksFixed++}})});let c=new Set(i.tasks.map(e=>e.id)),l=/* @__PURE__ */ new Set;i.tasks.forEach(e=>{e.subtasks&&Array.isArray(e.subtasks)&&e.subtasks.forEach(t=>{l.add(`${e.id}.${t.id}`)})}),i.tasks.forEach(t=>{if(t.dependencies&&Array.isArray(t.dependencies)){let e=t.dependencies.length;t.dependencies=t.dependencies.filter(e=>{if(String(e)===String(t.id))return n.push({type:`self`,taskId:t.id}),s.selfDependenciesRemoved++,!1;if(typeof e==`string`&&e.includes(`.`))return l.has(e)?!0:(n.push({type:`missing`,taskId:t.id,dependencyId:e}),s.nonExistentDependenciesRemoved++,!1);{let r=typeof e==`string`?parseInt(e,10):e;return c.has(r)?!0:(n.push({type:`missing`,taskId:t.id,dependencyId:e}),s.nonExistentDependenciesRemoved++,!1)}}),t.dependencies.length<e&&s.tasksFixed++}t.subtasks&&Array.isArray(t.subtasks)&&t.subtasks.forEach(r=>{if(r.dependencies&&Array.isArray(r.dependencies)){let i=r.dependencies.length,a=`${t.id}.${r.id}`;r.dependencies.some(e=>typeof e==`string`&&e.includes(`.`)?e===a:o(e)?e===r.id:!1)&&(r.dependencies=r.dependencies.filter(r=>e(t.id,r)!==a||(n.push({type:`self`,taskId:a}),s.selfDependenciesRemoved++,!1))),r.dependencies=r.dependencies.filter(e=>{if(typeof e==`string`&&e.includes(`.`))return l.has(e)?!0:(n.push({type:`missing`,taskId:a,dependencyId:e}),s.nonExistentDependenciesRemoved++,!1);let r=typeof e==`number`?e:parseInt(e,10);if(o(e)){let e=`${t.id}.${r}`;return l.has(e)?!0:(n.push({type:`missing`,taskId:a,dependencyId:e}),s.nonExistentDependenciesRemoved++,!1)}return c.has(r)?!0:(n.push({type:`missing`,taskId:a,dependencyId:e}),s.nonExistentDependenciesRemoved++,!1)}),r.dependencies.length<i&&s.subtasksFixed++}})}),d(`debug`,`Checking for circular dependencies...`);let u=/* @__PURE__ */ new Map;i.tasks.forEach(t=>{t.subtasks&&Array.isArray(t.subtasks)&&t.subtasks.forEach(n=>{let r=`${t.id}.${n.id}`;if(n.dependencies&&Array.isArray(n.dependencies)){let i=n.dependencies.map(n=>typeof n==`string`&&n.includes(`.`)?n:e(t.id,n));u.set(r,i)}else u.set(r,[])})});let f=(e,t,n=/* @__PURE__ */ new Set)=>e===t||!n.has(e)&&(n.add(e),(u.get(e)||[]).some(e=>f(e,t,n)));for(let[t,r]of u.entries()){let[a,o]=t.split(`.`).map(Number),c=i.tasks.find(e=>e.id===a)?.subtasks?.find(e=>e.id===o);if(c?.dependencies)for(let i of[...r]){if(!f(i,t))continue;let o=c.dependencies.length;c.dependencies=c.dependencies.filter(t=>e(a,t)!==i),r.splice(r.indexOf(i),1),c.dependencies.length<o&&(n.push({type:`circular`,taskId:t,dependencyId:i}),s.circularDependenciesFixed++,s.subtasksFixed++)}}Le(i.tasks);let p=JSON.stringify(i)!==JSON.stringify(a);return p?(E(t,i,r.projectRoot,r.tag),d(`debug`,`Fixed ${n.length} dependency problems`,s)):d(`debug`,`No changes needed to fix dependencies`),{fixes:n,remaining:Ge(i.tasks).issues,changed:p,...qe(i.tasks)}}catch(e){throw X(Y.FIX_FAILED,`Couldn't fix dependencies: ${e.message}`,void 0,e)}}function Xe(e,t,n,r=!1){let i=parseInt(e,10),a=n.find(e=>e.id===i);if(a&&a.subtasks&&Array.isArray(a.subtasks)){let n=a.subtasks.find(e=>r?String(e.id)===String(t):e.id===t);if(n)return{...n,id:`${e}.${n.id}`}}return null}function Ze(e,t,n){if(!e)return null;let r=String(e),i=null;if(i=n.find(e=>String(e.id)===r),!i&&r.includes(`.`)){let[e,t]=r.split(`.`);i=Xe(e,t,n,!0)}if(!i&&!isNaN(e)){let r=parseInt(e,10);if(t&&typeof t==`string`&&t.includes(`.`)){let[e]=t.split(`.`);i=Xe(e,r,n,!1)}}return i}function Qe(e,t,n){let r=[];return!Array.isArray(e.dependencies)||e.dependencies.length===0||e.dependencies.filter(e=>e!=null).forEach(i=>{let a=Ze(i,e.id,n);a&&a.tag!==t&&r.push({taskId:e.id,dependencyId:i,dependencyTag:a.tag,message:`Task ${e.id} depends on ${i} (in ${a.tag})`})}),r}function $e(e,t,n,r){if(!Array.isArray(e))throw Error(`Source tasks parameter must be an array`);if(!t||typeof t!=`string`)throw Error(`Source tag must be a valid string`);if(!n||typeof n!=`string`)throw Error(`Target tag must be a valid string`);if(!Array.isArray(r))throw Error(`All tasks parameter must be an array`);let i=[];return e.forEach(e=>{if(!e||typeof e!=`object`||!Array.isArray(e.dependencies)||e.dependencies.length===0)return;let t=Qe(e,n,r);i.push(...t)}),i}function et(e,t,n){if(!e||typeof e!=`string`)throw new Re(Y.INVALID_TASK_ID,`Task ID must be a valid string`);if(!t||typeof t!=`string`)throw new Re(Y.INVALID_SOURCE_TAG,`Source tag must be a valid string`);if(!n||typeof n!=`string`)throw new Re(Y.INVALID_TARGET_TAG,`Target tag must be a valid string`);if(e.includes(`.`))throw new Re(Y.CANNOT_MOVE_SUBTASK,`Cannot move subtask ${e} directly between tags.
2
-
3
- First promote it to a full task using:
4
- taskgraph remove-subtask --id=${e} --convert`,{taskId:e,sourceTag:t,targetTag:n})}async function tt(e,t,n=null,r=null,i=!1,a={}){let{projectRoot:o,tag:s}=a;try{d(`debug`,`Adding subtask to parent task ${t}...`);let i=M(e,o,s);if(!i||!i.tasks)throw Error(`Invalid or missing tasks file at ${e}`);let a=parseInt(t,10),l=i.tasks.find(e=>e.id===a);if(!l)throw Error(`Parent task with ID ${a} not found`);l.subtasks||=[];let u;if(n!==null){let e=parseInt(n,10),t=i.tasks.findIndex(t=>t.id===e);if(t===-1)throw Error(`Task with ID ${e} not found`);let r=i.tasks[t];if(r.parentTaskId)throw Error(`Task ${e} is already a subtask of task ${r.parentTaskId}`);if(e===a)throw Error(`Cannot make a task a subtask of itself`);if(kt(i.tasks,l,e))throw Error(`Cannot create circular dependency: task ${a} is already a subtask or dependent of task ${e}`);let o=(l.subtasks.length>0?Math.max(...l.subtasks.map(e=>e.id)):0)+1,{dependencies:s,metadata:f}=Me(r,a);u={...r,id:o,parentTaskId:a,dependencies:s},c(u,f),l.subtasks.push(u),i.tasks.splice(t,1),Ne(i.tasks,String(e),`${a}.${o}`),d(`debug`,`Converted task ${e} to subtask ${a}.${o}`)}else if(r){let e=(l.subtasks.length>0?Math.max(...l.subtasks.map(e=>e.id)):0)+1;u={id:e,title:r.title,description:r.description||``,details:r.details||``,status:r.status||`pending`,dependencies:r.dependencies||[],parentTaskId:a},l.subtasks.push(u),d(`debug`,`Created new subtask ${a}.${e}`)}else throw Error(`Either existingTaskId or newSubtaskData must be provided`);return E(e,i,o,s),u}catch(e){throw d(`debug`,`Error adding subtask: ${e.message}`),e}}const nt=[`high`,`medium`,`low`],rt=`medium`;function it(e){return nt.includes(e?.toLowerCase())}function at(e){if(!e)return null;let t=e.toLowerCase();return it(t)?t:null}const ot=K.object({title:K.string().describe(`Clear, concise title for the task`),description:K.string().describe(`A one or two sentence description of the task`),details:K.string().describe(`In-depth implementation details, considerations, and guidance`),testStrategy:K.string().describe(`Detailed approach for verifying task completion`),dependencies:K.array(K.number()).nullable().describe(`Array of task IDs that this task depends on (must be completed before this task can start)`)}).strict(),st=K.object({taskId:K.number().int().positive(),taskTitle:K.string(),complexityScore:K.number().min(1).max(10),recommendedSubtasks:K.number().int().nonnegative(),expansionPrompt:K.string(),reasoning:K.string()}).strict(),ct=K.object({complexityAnalysis:K.array(st)}).strict(),lt=K.enum([`pending`,`in-progress`,`blocked`,`done`,`cancelled`,`deferred`]),ut=K.object({id:K.number().int().positive(),title:K.string().min(1).max(200),description:K.string().min(1),status:lt,dependencies:K.array(K.union([K.number().int().positive(),K.string()])),priority:K.enum([`low`,`medium`,`high`,`critical`]).nullable(),details:K.string().nullable(),testStrategy:K.string().nullable()}).strict(),dt=K.object({id:K.number().int().positive(),title:K.string().min(5).max(200),description:K.string().min(10),dependencies:K.array(K.number().int().positive()),details:K.string().min(20),status:K.enum([`pending`,`done`,`completed`]),testStrategy:K.string().nullable()}).strict(),ft=K.object({subtasks:K.array(dt)}).strict(),pt=K.object({id:K.number().int().positive(),title:K.string().min(1),description:K.string().min(1),details:K.string().nullable(),testStrategy:K.string().nullable(),priority:K.enum([`high`,`medium`,`low`]).nullable(),dependencies:K.array(K.number().int().positive()).nullable(),status:K.string().nullable()}).strict(),mt=K.object({tasks:K.array(pt)}).strict(),ht=K.object({subtask:dt}).strict(),gt=ut.extend({subtasks:K.array(dt).nullable()}).strict(),_t={"update-tasks":K.object({tasks:K.array(gt)}).strict(),"expand-task":ft,"analyze-complexity":ct,"update-subtask-by-id":ht,"update-task-by-id":K.object({task:gt}),"add-task":ot,"parse-prd":mt};async function vt(e,t,n,r={}){let i;return await ie(e,a=>{let o=a??{};!o[t]&&r.createWith&&Object.keys(o).length===0&&(o[t]=r.createWith);let s=o[t];if(!s||!Array.isArray(s.tasks))throw Error(`Tag "${t}" no longer exists in ${e}`);return i=n(s),o}),i}function yt(e){let t=[];for(let n in e)Object.prototype.hasOwnProperty.call(e,n)&&e[n]&&Array.isArray(e[n].tasks)&&(t=t.concat(e[n].tasks));return t}async function bt(e,t,n=[],r=null,a={},o=`text`,s=null,l=!1){let{session:u,mcpLog:f,projectRoot:m,commandName:h,outputType:g,tag:_}=a,v=!!f,y=v?f:{info:(...e)=>d(`info`,...e),warn:(...e)=>d(`warn`,...e),error:(...e)=>d(`error`,...e),debug:(...e)=>d(`debug`,...e),success:(...e)=>d(`success`,...e)},x=r||w(m)||`medium`;if(r){let e=at(r);e?x=e:(o===`text`&&d(`warn`,`Invalid priority "${r}". Using default priority "${rt}".`),x=rt)}y.debug(`Adding new task with prompt: "${t}", Priority: ${x}, Dependencies: ${n.join(`, `)||`None`}, Research: ${l}, ProjectRoot: ${m}`),_&&y.debug(`Using tag context: ${_}`);let S=null,T=null,E=(e,t=`info`)=>{f?f[t](e):o===`text`&&d(t,e)};function O(e,t,n=/* @__PURE__ */ new Set,r=/* @__PURE__ */ new Map,i=0){if(n.has(t))return null;let a=e.find(e=>e.id===t);if(!a)return null;n.add(t),(!r.has(t)||i<r.get(t))&&r.set(t,i);let o=[];if(a.dependencies&&a.dependencies.length>0)for(let t of a.dependencies){let a=O(e,t,n,r,i+1);a&&o.push(a)}return{id:a.id,title:a.title,description:a.description,status:a.status,dependencies:o}}try{let r=M(e,m,_);r&&r._rawTaggedData&&(r=r._rawTaggedData),r||=(E(`tasks.json not found or invalid. Initializing new structure.`,`info`),{master:{tasks:[],metadata:{created:(/* @__PURE__ */ new Date()).toISOString(),description:`Default tasks context`}}}),r&&Array.isArray(r.tasks)&&!r._rawTaggedData&&(E(`Legacy format detected. Migrating to tagged format...`,`info`),r={master:{tasks:r.tasks,metadata:r.metadata||{created:(/* @__PURE__ */ new Date()).toISOString(),updated:(/* @__PURE__ */ new Date()).toISOString(),description:`Tasks for master context`}}},b(r.master,{description:`Tasks for master context`}),ee(e),D(e),E(`Successfully migrated to tagged format.`,`success`));let a=_;if(!r[a])throw E(`Tag "${a}" does not exist. Please create it first using the 'add-tag' command.`,`error`),Error(`Tag "${a}" not found.`);r[a].tasks||(r[a].tasks=[]),r[a].metadata||(r[a].metadata={created:(/* @__PURE__ */ new Date()).toISOString(),updated:(/* @__PURE__ */ new Date()).toISOString(),description:``});let d=yt(r),f=r[a].tasks,y=(f.length>0?Math.max(...f.map(e=>e.id)):0)+1,w=n.filter(e=>{let t=parseInt(e,10);return Number.isNaN(t)||!d.some(e=>e.id===t)});w.length>0&&(E(`The following dependencies do not exist or are invalid: ${w.join(`, `)}`,`warn`),E(`Removing invalid dependencies...`,`info`),n=n.filter(e=>!w.includes(e)));let k=n.map(e=>parseInt(e,10)),A=[],j=/* @__PURE__ */ new Set,N=/* @__PURE__ */ new Map;for(let e of k){let t=O(d,e,/* @__PURE__ */ new Set,N);t&&A.push(t)}for(let[e,t]of N.entries())j.add(e);let F;if(s){if(E(`Using manually provided task data`,`info`),F=s,E(`DEBUG: Taking MANUAL task data path.`,`debug`),!F.title||typeof F.title!=`string`||!F.description||typeof F.description!=`string`)throw Error(`Manual task data must include at least a title and description.`)}else{E(`DEBUG: Taking AI task generation path.`,`debug`),E(`Generating task data with AI with prompt:\n${t}`,`debug`);let e=await new ge(m,_).gather({semanticQuery:t,dependencyTasks:k,format:`research`}),n=e.context,r=e.analysisData;o===`text`&&r&&me(r,t,n.length);let i=``;s?.title&&(i+=`\n- Suggested Title: "${s.title}"`),s?.description&&(i+=`\n- Suggested Description: "${s.description}"`),s?.details&&(i+=`\n- Additional Details Context: "${s.details}"`),s?.testStrategy&&(i+=`\n- Additional Test Strategy Context: "${s.testStrategy}"`);let{systemPrompt:a,userPrompt:c}=await pe().loadPrompt(`add-task`,{prompt:t,newTaskId:y,existingTasks:d,gatheredContext:n,contextFromArgs:i,useResearch:l,priority:x,dependencies:k,hasCodebaseAnalysis:p(l,m,u),projectRoot:m});o===`text`&&(S=U(`Writing the new task${l?` with research`:``}…`));try{let e=l?`research`:`main`;if(E(`DEBUG: Calling generateObjectService...`,`debug`),T=await W({role:e,session:u,projectRoot:m,schema:_t[`add-task`],objectName:`newTaskData`,systemPrompt:a,prompt:c,commandName:h||`add-task`,outputType:g||(v?`mcp`:`cli`)}),E(`DEBUG: generateObjectService returned successfully.`,`debug`),!T||!T.mainResult)throw Error(`AI service did not return the expected object structure.`);if(T.mainResult.title&&T.mainResult.description)F=T.mainResult;else if(T.mainResult.object&&T.mainResult.object.title&&T.mainResult.object.description)F=T.mainResult.object;else throw Error(`AI service did not return a valid task object.`);E(`Successfully generated task data from AI.`,`debug`),S&&=(B(S),null)}catch(e){throw S&&=(V(S,`AI generation failed`),null),E(`DEBUG: generateObjectService caught error: ${e.message}`,`debug`),E(`Error generating task with AI: ${e.message}`,`error`),e}finally{E(`DEBUG: generateObjectService finally block reached.`,`debug`),S&&B(S)}}let I={id:y,title:F.title,description:F.description,details:F.details||``,testStrategy:F.testStrategy||``,status:`pending`,dependencies:F.dependencies?.length?F.dependencies:k,priority:x,subtasks:[]};if(F.dependencies?.length&&(F.dependencies.every(e=>{let t=parseInt(e,10);return!Number.isNaN(t)&&d.some(e=>e.id===t)})||(E(`AI suggested invalid dependencies. Filtering them out...`,`warn`),I.dependencies=F.dependencies.filter(e=>{let t=parseInt(e,10);return!Number.isNaN(t)&&d.some(e=>e.id===t)}))),c(I,i(I,{dependencies:k})),E(`DEBUG: Writing tasks.json...`,`debug`),await vt(e,a,e=>{e.tasks.some(e=>e.id===I.id)&&(I.id=Math.max(...e.tasks.map(e=>e.id))+1),e.tasks.push(I),b(e,{description:`Tasks for ${a} context`})},{createWith:r[a]}),y=I.id,E(`DEBUG: tasks.json written.`,`debug`),o===`text`){let e=e=>{switch(e?.toLowerCase()){case`high`:return`red`;case`low`:return`dim`;default:return`yellow`}},t=I.dependencies.filter(e=>!k.includes(e)),n=k.filter(e=>!I.dependencies.includes(e)),r={};I.dependencies.forEach(e=>{let t=d.find(t=>t.id===e);t&&(r[e]=P(t.title,30))});let i=``;I.dependencies.length>0?(i=C.text(`Dependencies:`)+`
5
- `,I.dependencies.forEach(e=>{let n=t.includes(e)?G.yellow(` (AI suggested)`):``;i+=C.text(` - ${e}: ${r[e]||`Unknown task`}${n}`)+`
6
- `})):i=C.text(`Dependencies: None`)+`
7
- `,n.length>0&&(i+=C.muted(`
8
- User-specified dependencies that were not used:`)+`
9
- `,n.forEach(e=>{let t=d.find(t=>t.id===e),n=t?P(t.title,30):`Unknown task`;i+=C.muted(` - ${e}: ${n}`)+`
10
- `}));let a=``;(t.length>0||n.length>0)&&(a=`
11
- `+C.text.bold(`Dependency Analysis:`)+`
12
- `,t.length>0&&(a+=G.green(`AI identified ${t.length} additional dependencies`)+`
13
- `),n.length>0&&(a+=G.yellow(`AI excluded ${n.length} user-provided dependencies`)+`
14
- `)),console.log(J(C.text.bold(`Task ${y} Created Successfully`)+`
15
-
16
- `+C.text(`Title: ${I.title}`)+`
17
- `+C.text(`Status: ${Se(I.status)}`)+`
18
- `+C.text(`Priority: ${G[e(I.priority)](I.priority)}`)+`
19
-
20
- `+i+a+`
21
- `+C.text.bold(`Next Steps:`)+`
22
- `+G.cyan(`1. Run ${G.yellow(`taskgraph show ${y}`)} to see complete task details`)+`
23
- `+G.cyan(`2. Run ${G.yellow(`taskgraph set-status --id=${y} --status=in-progress`)} to start working on it`)+`
24
- `+G.cyan(`3. Run ${G.yellow(`taskgraph expand --id=${y}`)} to break it down into subtasks`),{padding:1,borderColor:`green`,borderStyle:`round`})),T&&T.telemetryData&&(g===`cli`||g===`text`)&&H(T.telemetryData,`cli`)}return E(`DEBUG: Returning new task ID: ${y} and telemetry.`,`debug`),{newTaskId:y,telemetryData:T?T.telemetryData:null,tagInfo:T?T.tagInfo:null}}catch(e){throw S&&B(S),o!==`text`&&E(`Error adding task: ${e.message}`,`error`),e}}function xt(e,t){let n=Ee.relative(t||process.cwd(),e);return n&&!n.startsWith(`..`)?n:e}async function St(e,t={}){let{session:n,mcpLog:r}=t,i=e.file||`.taskgraph/tasks/tasks.json`,a=parseFloat(e.threshold||`5`),o=e.research||!1,s=e.projectRoot,c=e.tag,l=e.id?e.id.split(`,`).map(e=>parseInt(e.trim(),10)).filter(e=>!Number.isNaN(e)):null,u=e.from===void 0?null:parseInt(e.from,10),f=e.to===void 0?null:parseInt(e.to,10),m=r?`json`:`text`,g=(e,t=`info`)=>{r?r[t](e):!v()&&m===`text`&&d(t===`warn`||t===`error`?t:`debug`,e)},_=se(e.output,{projectRoot:s,tag:c},g);try{g(`Reading tasks from ${i}...`,`info`);let t,v=0,y=null,b=0;if(e._filteredTasksData){if(t=e._filteredTasksData,v=e._originalTaskCount||t.tasks.length,!e._originalTaskCount)try{y=M(i,s,c),y&&y.tasks&&(v=y.tasks.length)}catch(e){d(`warn`,`Could not read original tasks file: ${e.message}`)}}else{if(y=M(i,s,c),!y||!y.tasks||!Array.isArray(y.tasks)||y.tasks.length===0)throw Error(`No tasks found in the tasks file`);v=y.tasks.length;let e=[`pending`,`blocked`,`in-progress`],n=t=>e.includes(t.status?.toLowerCase()||`pending`),r=()=>!0,a=y.tasks.filter(n);if(l&&l.length>0){if(g(`Filtering tasks by specific IDs: ${l.join(`, `)}`,`info`),r=e=>l.includes(e.id),a=a.filter(r),m===`text`){if(a.length===0&&l.length>0)console.log(G.yellow(`Warning: No active tasks found with IDs: ${l.join(`, `)}`));else if(a.length<l.length){let e=a.map(e=>e.id),t=l.filter(t=>!e.includes(t));console.log(G.yellow(`Warning: Some requested task IDs were not found or are not active: ${t.join(`, `)}`))}}}else if(u!==null||f!==null){let e=u===null?1:u,t=f===null?Math.max(...y.tasks.map(e=>e.id)):f;g(`Filtering tasks by ID range: ${e} to ${t}`,`info`),r=n=>n.id>=e&&n.id<=t,a=a.filter(r),m===`text`&&a.length===0&&console.log(G.yellow(`Warning: No active tasks found in range: ${e}-${t}`))}b=y.tasks.filter(e=>r(e)&&!n(e)).length,t={...y,tasks:a,_originalTaskCount:v}}let x=``;if(y&&y.tasks.length>0)try{let e=new ge(s,c),n=h(y.tasks),r=new ve(n,`analyze-complexity`),i=t.tasks.map(e=>`${e.title} ${e.description}`).join(` `),a=r.findRelevantTasks(i,{maxResults:10}),o=r.getTaskIds(a);o.length>0&&(x=(await e.gather({tasks:o,format:`research`})).context||``)}catch(e){g(`Could not gather additional context: ${e.message}`,`warn`)}g(`Found ${v} total tasks in the task file.`,`info`),l||u!==null||f!==null?g(l?`Analyzing ${t.tasks.length} tasks with specific IDs: ${l.join(`, `)}`:`Analyzing ${t.tasks.length} tasks in range: ${u||1} to ${f||`end`}`,`info`):b>0&&g(`Skipping ${b} tasks marked as done/cancelled/deferred. Analyzing ${t.tasks.length} active tasks.`,`info`);let S=null,C=/* @__PURE__ */ new Map;try{q.existsSync(_)&&(S=JSON.parse(q.readFileSync(_,`utf8`)),g(`Found existing complexity report at ${_}`,`info`),S&&S.complexityAnalysis&&Array.isArray(S.complexityAnalysis)&&(S.complexityAnalysis.forEach(e=>{C.set(e.taskId,e)}),g(`Existing report contains ${S.complexityAnalysis.length} task analyses`,`info`)))}catch(e){g(`Warning: Could not read existing report: ${e.message}`,`warn`),S=null,C.clear()}if(t.tasks.length===0){if(S&&(l||u!==null||f!==null))return g(`No matching tasks found for analysis. Keeping existing report.`,`info`),m===`text`&&console.log(G.dim(`The complexity report is unchanged`)),{report:S,telemetryData:null};let e={meta:{generatedAt:(/* @__PURE__ */ new Date()).toISOString(),tasksAnalyzed:0,thresholdScore:a,projectName:O(n),usedResearch:o},complexityAnalysis:S?.complexityAnalysis||[]};return g(`Writing complexity report to ${_}...`,`info`),q.writeFileSync(_,JSON.stringify(e,null,` `),`utf8`),g(`Task complexity analysis complete. Report written to ${_}`,`success`),m===`text`&&console.log(R({analyses:[],skipped:b,kept:0,reportPath:xt(_,s)})),{report:e,telemetryData:null}}let w=pe(),T={tasks:t.tasks,gatheredContext:x||``,useResearch:o,hasCodebaseAnalysis:p(o,s,n),projectRoot:s||``},{systemPrompt:E,userPrompt:D}=await w.loadPrompt(`analyze-complexity`,T,`default`),k=null;if(m===`text`){let e=t.tasks.length;k=U(`Analyzing ${e} ${e===1?`task`:`tasks`}${o?` with web research`:``}…`)}let A=null,j=null;try{A=await W({prompt:D,systemPrompt:E,role:o?`research`:`main`,session:n,projectRoot:s,schema:_t[`analyze-complexity`],objectName:`complexityAnalysis`,commandName:`analyze-complexity`,outputType:r?`mcp`:`cli`}),k&&=(B(k),null),j=A.mainResult?.complexityAnalysis,g(`Received ${j.length} complexity analyses from AI.`,`info`);let e=t.tasks.map(e=>e.id),i=j.map(e=>e.taskId),c=e.filter(e=>!i.includes(e));if(c.length>0){g(`Missing analysis for ${c.length} tasks: ${c.join(`, `)}`,`warn`);for(let e of c){let n=t.tasks.find(t=>t.id===e);n&&(g(`Adding default analysis for task ${e}`,`info`),j.push({taskId:e,taskTitle:n.title,complexityScore:5,recommendedSubtasks:3,expansionPrompt:`Break down this task with a focus on ${n.title.toLowerCase()}.`,reasoning:`Automatically added due to missing analysis in AI response.`}))}}let l=[];if(S&&Array.isArray(S.complexityAnalysis)){let e=new Set(j.map(e=>e.taskId)),n=new Set((y?.tasks??t.tasks).map(e=>e.id)),r=S.complexityAnalysis.filter(t=>!e.has(t.taskId)&&n.has(t.taskId));l=[...r,...j],g(`Merged ${j.length} new analyses with ${r.length} existing entries from current tag`,`info`)}else l=j;let u={meta:{generatedAt:(/* @__PURE__ */ new Date()).toISOString(),tasksAnalyzed:t.tasks.length,totalTasks:v,analysisCount:l.length,thresholdScore:a,projectName:O(n),usedResearch:o},complexityAnalysis:l};return g(`Writing complexity report to ${_}...`,`info`),q.writeFileSync(_,JSON.stringify(u,null,` `),`utf8`),g(`Task complexity analysis complete. Report written to ${_}`,`success`),m===`text`&&(console.log(R({analyses:j,skipped:b,kept:l.length-j.length,reportPath:xt(_,s),usedResearch:o})),F(n)&&console.debug(G.dim(`Final analysis object: ${JSON.stringify(u,null,2)}`)),A.telemetryData&&H(A.telemetryData,`cli`)),{report:u,telemetryData:A?.telemetryData,tagInfo:A?.tagInfo}}catch(e){throw k&&B(k),r&&g(`Error during AI service call: ${e.message}`,`error`),e}}catch(e){if(r&&g(`Error analyzing task complexity: ${e.message}`,`error`),m===`text`)ce(`Couldn't analyze task complexity: ${e.message}`),F(n)&&console.error(e),process.exit(1);else throw e}}var Ct=class extends Error{constructor(e,t,n){super(t),this.name=`ClearSubtasksError`,this.code=e,this.taskId=n}};function wt(e,t){let n=[...new Set(String(t).split(`,`).map(e=>e.trim()).filter(Boolean))];if(n.length===0)throw new Ct(`INVALID_TASK_ID`,`No task IDs given`);return n.map(t=>{if(/^\d+\.\d+/.test(t))throw new Ct(`SUBTASK_ID`,`${t} is a subtask, not a task`,t);if(!/^\d+$/.test(t))throw new Ct(`INVALID_TASK_ID`,`"${t}" isn't a task ID`,t);let n=e.find(e=>String(e.id)===t);if(!n)throw new Ct(`TASK_NOT_FOUND`,`Task ${t} not found`,t);return n})}function Tt(e,t,n={}){let{projectRoot:r,tag:i}=n;d(`debug`,`Reading tasks from ${e}...`);let a=M(e,r,i);if(!a||!a.tasks)throw new Ct(`NO_TASKS`,`No valid tasks found`);let o=wt(a.tasks,t),s=[],c=[];for(let e of o){let t=e.subtasks?.length??0;t===0?c.push({id:e.id,title:e.title}):(e.subtasks=[],s.push({id:e.id,title:e.title,count:t}),d(`debug`,`Cleared ${t} subtasks from task ${e.id}`))}return s.length>0&&E(e,a,r,i),{cleared:s,empty:c}}function Et(e,t){let n=!!e,r=e||{info:e=>!v()&&d(`info`,e),warn:e=>!v()&&d(`warn`,e),error:e=>!v()&&d(`error`,e),debug:e=>!v()&&F(t)&&d(`debug`,e)};return{logger:r,report:(e,...t)=>{n?typeof r[e]==`function`?r[e](...t):r.info(...t):v()||d(e,...t)},isMCP:n}}async function Dt(e,t,n,r=!1,a=``,o={},s=!1){let{session:l,mcpLog:u,projectRoot:d,tag:f,complexityReportPath:g}=o,_=u?`json`:`text`,v=d||m(e),{logger:y,report:b,isMCP:x}=Et(u,l);x&&y.debug(`expandTask called with context: session=${!!l}`);try{y.debug(`Reading tasks from ${e}`);let o=M(e,v,f);if(!o||!o.tasks)throw Error(`Invalid tasks data in ${e}`);let u=o.tasks.findIndex(e=>e.id===parseInt(t,10));if(u===-1)throw Error(`Task ${t} not found`);let d=o.tasks[u];y.debug(`Expanding task ${t}: ${d.title}${r?` with research`:``}`),s&&Array.isArray(d.subtasks)&&d.subtasks.length>0&&(y.debug(`Force flag set. Clearing existing ${d.subtasks.length} subtasks for task ${t}.`),d.subtasks=[]);let m=``;try{let e=new ge(v,f),n=h(o.tasks),r=new ve(n,`expand-task`),i=`${d.title} ${d.description}`,a=r.findRelevantTasks(i,{maxResults:5,includeSelf:!0}),s=r.getTaskIds(a),c=[.../* @__PURE__ */ new Set([t.toString(),...s])];c.length>0&&(m=(await e.gather({tasks:c,format:`research`})).context||``)}catch(e){y.warn(`Could not gather context: ${e.message}`)}let b,x=``,S=null;y.debug(`Looking for complexity report at: ${g}${f===`master`?``:` (tag-specific for '${f}')`}`);try{q.existsSync(g)?(S=M(g)?.complexityAnalysis?.find(e=>e.taskId===d.id),S?(y.debug(`Found complexity analysis for task ${d.id}: Score ${S.complexityScore}`),S.reasoning&&(x=`\nComplexity Analysis Reasoning: ${S.reasoning}`)):y.debug(`No complexity analysis found for task ${d.id} in report.`)):y.debug(`Complexity report not found at ${g}. Skipping complexity check.`)}catch(e){y.warn(`Could not read or parse complexity report: ${e.message}. Proceeding without it.`)}let C=parseInt(n,10);if(!Number.isNaN(C)&&C>=0)b=C,y.debug(`Using explicitly provided subtask count: ${b}`);else if(S?.recommendedSubtasks!=null){if(b=parseInt(S.recommendedSubtasks,10),y.debug(`Using subtask count from complexity report: ${b}`),b===0)return y.debug(`Complexity report recommends no expansion for task ${t}. Skipping.`),{task:d,skipped:!0}}else b=N(l),y.debug(`Using default number of subtasks: ${b}`);(Number.isNaN(b)||b<0)&&(y.warn(`Invalid subtask count determined (${b}), defaulting to 3.`),b=3);let w=(d.subtasks?.length||0)+1,T=pe(),E=p(r,v,l),D=``;(a||x)&&(D=`\n\n${a}${x}`.trim()),m&&(D=`${D}\n\n# Project Context\n\n${m}`.trim());let O;S?.expansionPrompt&&(typeof S.expansionPrompt==`string`?O=S.expansionPrompt:typeof S.expansionPrompt==`object`&&S.expansionPrompt.text&&(O=S.expansionPrompt.text));let k=m;typeof m==`object`&&m&&(k=m.data?m.data:m.text?m.text:JSON.stringify(m));let A={task:d,subtaskCount:b,nextSubtaskId:w,additionalContext:a,complexityReasoningContext:x,gatheredContext:k||``,useResearch:r,expansionPrompt:O||void 0,hasCodebaseAnalysis:E,projectRoot:v||``},j=`default`;O?(j=`complexity-report`,y.debug(`Using expansion prompt from complexity report for task ${d.id}.`)):r?(j=`research`,y.debug(`Using research variant for task ${d.id}.`)):y.debug(`Using standard prompt generation for task ${d.id}.`);let{systemPrompt:P,userPrompt:ee}=T.loadPrompt(`expand-task`,A,j);y.debug(`Selected variant: ${j}`),y.debug(`Prompt params passed: ${JSON.stringify(A,null,2)}`),y.debug(`System prompt (first 500 chars): ${P.substring(0,500)}...`),y.debug(`User prompt (first 500 chars): ${ee.substring(0,500)}...`);let F=[],I=null;_===`text`&&(I=U(`Breaking task ${d.id} into ${b||`a few`} subtasks…`));let L=null;try{L=await W({prompt:ee,systemPrompt:P,role:r?`research`:`main`,session:l,projectRoot:v,schema:_t[`expand-task`],objectName:`subtasks`,commandName:`expand-task`,outputType:_});let e=L?.mainResult;if(!e||!Array.isArray(e.subtasks))throw Error(`AI response did not include a valid subtasks array.`);F=e.subtasks.map(e=>{let t={...e,dependencies:e.dependencies??[],status:e.status??`pending`,testStrategy:e.testStrategy??null};return c(t,i(t,void 0,d.id)),t}),y.debug(`Received ${F.length} subtasks from AI.`)}catch(e){throw I&&B(I),e}finally{I&&B(I)}return await vt(e,f??o.tag??`master`,e=>{let n=e.tasks.find(e=>e.id===d.id);if(!n)throw Error(`Task ${t} was removed while it was being expanded`);(s||!Array.isArray(n.subtasks))&&(n.subtasks=[]),n.subtasks.push(...F),d=n}),_===`text`&&ye(d.id,F),_===`text`&&L&&L.telemetryData&&H(L.telemetryData,`cli`),{task:d,telemetryData:L?.telemetryData,tagInfo:L?.tagInfo}}catch(e){throw _!==`text`&&y.error(`Error expanding task ${t}: ${e.message}`,`error`),e}}async function Ot(e,t,n=!1,r=``,i=!1,a={},o=`text`){let{session:s,mcpLog:c,projectRoot:l,tag:u,complexityReportPath:f}=a,p=!!c,h=l||m();if(!h)throw Error(`Could not determine project root directory`);let g=c||(o===`json`?{info:e=>{},warn:e=>{},error:e=>console.error(`ERROR: ${e}`),debug:e=>{}}:{info:e=>!v()&&d(`info`,e),warn:e=>!v()&&d(`warn`,e),error:e=>!v()&&d(`error`,e),debug:e=>!v()&&F(s)&&d(`debug`,e)}),_=null,b=0,x=0,S=0,w=0,T=[];!p&&o===`text`&&(_=U(`Analyzing tasks for expansion...`));try{g.debug(`Reading tasks from ${e}`);let s=M(e,h,u);if(!s||!s.tasks)throw Error(`Invalid tasks data in ${e}`);let c=s.tasks.filter(e=>(e.status===`pending`||e.status===`in-progress`)&&(!e.subtasks||e.subtasks.length===0||i));if(w=c.length,g.info(`Found ${w} tasks eligible for expansion.`),_&&B(_,`Analysis complete.`),w===0)return g.info(`No tasks eligible for expansion.`),{success:!0,expandedCount:0,failedCount:0,skippedCount:0,tasksToExpand:0,telemetryData:T,message:`No tasks eligible for expansion.`};for(let l of c){let c=null;!p&&o===`text`&&(c=U(`Expanding task ${l.id}...`));try{let o=await Dt(e,l.id,t,n,r,{...a,projectRoot:h,tag:s.tag||u,complexityReportPath:f},i);if(o?.skipped){S++,c&&B(c,`Task ${l.id} skipped (no expansion recommended).`),g.info(`Skipped task ${l.id}: complexity report recommends no expansion.`);continue}b++,o&&o.telemetryData&&T.push(o.telemetryData),c&&B(c,`Task ${l.id} expanded.`),g.info(`Successfully expanded task ${l.id}.`)}catch(e){x++,c&&B(c,`Failed to expand task ${l.id}.`,!1),g.error(`Failed to expand task ${l.id}: ${e.message}`)}}g.info(`Expansion complete: ${b} expanded, ${S} skipped, ${x} failed.`);let l=y(T,`expand-all-tasks`);if(o===`text`){let e=`${C.text.bold(`Expansion Summary:`)}\n\n${G.cyan(`-`)} Attempted: ${G.bold(w)}\n${G.green(`-`)} Expanded: ${G.bold(b)}\n${C.muted(`-`)} Skipped: ${G.bold(S)}\n${G.red(`-`)} Failed: ${G.bold(x)}`;console.log(J(e,{padding:1,margin:{top:1},borderColor:x>0?`red`:`green`,borderStyle:`round`}))}return o===`text`&&l&&H(l,`cli`),{success:!0,expandedCount:b,failedCount:x,skippedCount:S,tasksToExpand:w,telemetryData:l}}catch(e){throw _&&B(_,`Error.`,!1),g.error(`Error during expand all operation: ${e.message}`),!p&&F(s)&&console.error(e),e}}function kt(t,n,r,i){let a=String(r);if(n.parentTaskId!==void 0&&String(n.parentTaskId)===a)return!0;let o=(n.dependencies||[]).map(t=>i===void 0?String(t):e(i,t));if(o.includes(a))return!0;for(let e of o){let n=t.find(t=>String(t.id)===e);if(n&&kt(t,n,r))return!0}if(n.subtasks){for(let e of n.subtasks)if(kt(t,e,r,n.id))return!0}return!1}async function At(e,t,n=null,i=!1,a=`text`,o={}){let{projectRoot:s,tag:c}=o;try{let o;try{let e=await(await r({projectPath:s||process.cwd()})).tasks.list({tag:c});o={tasks:e.tasks},d(`debug`,`Loaded ${e.tasks.length} tasks via tm-core`)}catch(t){d(`warn`,`TmCore failed, falling back to legacy readJSON: ${t.message}`),o=M(e,s,c)}if(!o||!o.tasks)throw Error(`No valid tasks found in ${e}`);let l=ne(n);l&&l.complexityAnalysis&&o.tasks.forEach(e=>f(e,l));let u;if(t&&t.toLowerCase()!==`all`){let e=t.split(`,`).map(e=>e.trim().toLowerCase()).filter(e=>e.length>0);u=o.tasks.filter(t=>t.status&&e.includes(t.status.toLowerCase()))}else u=o.tasks;let p=o.tasks.length,m=o.tasks.filter(e=>e.status===`done`||e.status===`completed`).length,h=p>0?m/p*100:0,g=m,_=o.tasks.filter(e=>e.status===`in-progress`).length,v=o.tasks.filter(e=>e.status===`pending`).length,y=o.tasks.filter(e=>e.status===`blocked`).length,b=o.tasks.filter(e=>e.status===`deferred`).length,x=o.tasks.filter(e=>e.status===`cancelled`).length,S=o.tasks.filter(e=>e.status===`review`).length,C=0,w=0,T=0,E=0,D=0,O=0,k=0,A=0;o.tasks.forEach(e=>{e.subtasks&&e.subtasks.length>0&&(C+=e.subtasks.length,w+=e.subtasks.filter(e=>e.status===`done`||e.status===`completed`).length,T+=e.subtasks.filter(e=>e.status===`in-progress`).length,E+=e.subtasks.filter(e=>e.status===`pending`).length,D+=e.subtasks.filter(e=>e.status===`blocked`).length,O+=e.subtasks.filter(e=>e.status===`deferred`).length,k+=e.subtasks.filter(e=>e.status===`cancelled`).length,A+=e.subtasks.filter(e=>e.status===`review`).length)});let N=C>0?w/C*100:0,ee=new Set(o.tasks.filter(e=>e.status===`done`||e.status===`completed`).map(e=>e.id)),F=o.tasks.filter(e=>e.status!==`done`&&e.status!==`completed`&&(!e.dependencies||e.dependencies.length===0)).length,I=o.tasks.filter(e=>e.status!==`done`&&e.status!==`completed`&&e.dependencies&&e.dependencies.length>0&&e.dependencies.every(e=>ee.has(e))).length,L=o.tasks.filter(e=>e.status!==`done`&&e.status!==`completed`&&e.dependencies&&e.dependencies.length>0&&!e.dependencies.every(e=>ee.has(e))).length,te=F+I,re={};o.tasks.forEach(e=>{e.dependencies&&e.dependencies.length>0&&e.dependencies.forEach(e=>{re[e]=(re[e]||0)+1})});let ie=null,ae=0;for(let[e,t]of Object.entries(re))t>ae&&(ae=t,ie=parseInt(e));let oe=ie===null?null:o.tasks.find(e=>e.id===ie),se=o.tasks.reduce((e,t)=>e+(t.dependencies?t.dependencies.length:0),0)/o.tasks.length,R=ue(o.tasks,l);if(a===`json`)return{tasks:u.map(e=>{let{details:t,...n}=e;return n.subtasks&&Array.isArray(n.subtasks)&&(n.subtasks=n.subtasks.map(e=>{let{details:t,...n}=e;return n})),n}),filter:t||`all`,stats:{total:p,completed:g,inProgress:_,pending:v,blocked:y,deferred:b,cancelled:x,review:S,completionPercentage:h,subtasks:{total:C,completed:w,inProgress:T,pending:E,blocked:D,deferred:O,cancelled:k,completionPercentage:N}}};if(a===`markdown-readme`)return Mt(o,u,{totalTasks:p,completedTasks:m,completionPercentage:h,doneCount:g,inProgressCount:_,pendingCount:v,blockedCount:y,deferredCount:b,cancelledCount:x,totalSubtasks:C,completedSubtasks:w,subtaskCompletionPercentage:N,inProgressSubtasks:T,pendingSubtasks:E,blockedSubtasks:D,deferredSubtasks:O,cancelledSubtasks:k,reviewSubtasks:A,tasksWithNoDeps:F,tasksReadyToWork:te,tasksWithUnsatisfiedDeps:L,mostDependedOnTask:oe,mostDependedOnTaskId:ie,maxDependents:ae,avgDependenciesPerTask:se,complexityReport:l,withSubtasks:i,nextItem:R});if(a===`compact`)return It(u,i);let ce={"in-progress":p>0?_/p*100:0,pending:p>0?v/p*100:0,blocked:p>0?y/p*100:0,deferred:p>0?b/p*100:0,cancelled:p>0?x/p*100:0,review:p>0?S/p*100:0},B={"in-progress":C>0?T/C*100:0,pending:C>0?E/C*100:0,blocked:C>0?D/C*100:0,deferred:C>0?O/C*100:0,cancelled:C>0?k/C*100:0,review:C>0?A/C*100:0},de=he(h,30,ce),pe=he(N,30,B),V;try{V=process.stdout.columns}catch{d(`debug`,`Could not determine terminal width, using default`)}V||=80,V=Math.max(V,80);let H=G.bold(`Project Dashboard`)+`
25
- Tasks Progress: ${G.greenBright(de)} ${h.toFixed(0)}%\n${G.green(`█`)} Done: ${G.green(g)} ${G.cyan(`▓`)} In Progress: ${G.cyan(_)} ${G.yellow(`░`)} Pending: ${G.yellow(v)} ${G.red(`!`)} Blocked: ${G.red(y)} ${z.muted(`─`)} Deferred: ${z.muted(b)} ${z.muted(`─`)} Cancelled: ${z.muted(x)}\n\nSubtasks Progress: ${G.cyan(pe)} ${N.toFixed(0)}%\n${G.green(`█`)} Completed: ${G.green(w)}/${C} ${G.cyan(`▓`)} In Progress: ${G.cyan(T)} ${G.yellow(`░`)} Pending: ${G.yellow(E)} ${G.red(`!`)} Blocked: ${G.red(D)} ${z.muted(`─`)} Deferred: ${z.muted(O)} ${z.muted(`─`)} Cancelled: ${z.muted(k)}\n\n`+G.cyan.bold(`Priority Breakdown:`)+`
26
- ${G.red(`•`)} ${G.reset(`High priority:`)} ${o.tasks.filter(e=>e.priority===`high`).length}\n${G.yellow(`•`)} ${G.reset(`Medium priority:`)} ${o.tasks.filter(e=>e.priority===`medium`).length}\n${G.green(`•`)} ${G.reset(`Low priority:`)} ${o.tasks.filter(e=>e.priority===`low`).length}`,me=G.bold(`Dependency Status & Next Task`)+`
27
- `+G.cyan.bold(`Dependency Metrics:`)+`
28
- ${G.green(`•`)} ${G.reset(`Tasks with no dependencies:`)} ${F}\n${G.green(`•`)} ${G.reset(`Tasks ready to work on:`)} ${te}\n${G.yellow(`•`)} ${G.reset(`Tasks blocked by dependencies:`)} ${L}\n${G.magenta(`•`)} ${G.reset(`Most depended-on task:`)} ${oe?G.cyan(`#${ie} (${ae} dependents)`):z.muted(`None`)}\n${G.cyan(`•`)} ${G.reset(`Avg dependencies per task:`)} ${se.toFixed(1)}\n\n`+G.cyan.bold(`Next Task:`)+`
29
- ID: ${G.cyan(R?R.id:`N/A`)} - ${R?G.bold(P(R.title,40)):G.yellow(`No task available`)}
30
- Priority: ${R?G.reset(R.priority||`medium`):``} Dependencies: ${R?fe(R.dependencies,o.tasks,!0,l):``}
31
- Complexity: ${R&&R.complexityScore?be(R.complexityScore):z.muted(`N/A`)}`;if(V>=104){let e=Math.floor(V/2),t=e-4,n=J(H,{padding:1,borderColor:_e,borderStyle:`round`,width:t,dimBorder:!1}),r=J(me,{padding:1,borderColor:`magenta`,borderStyle:`round`,width:t,dimBorder:!1}),i=n.split(`
32
- `),a=r.split(`
33
- `),o=Math.max(i.length,a.length),s=[];for(let t=0;t<o;t++){let n=t<i.length?i[t]:``,r=t<a.length?a[t]:``,o=n.trimEnd().padEnd(e,` `);s.push(o+r)}console.log(s.join(`
34
- `))}else{let e=J(H,{padding:1,borderColor:_e,borderStyle:`round`,margin:{top:0,bottom:1}}),t=J(me,{padding:1,borderColor:`magenta`,borderStyle:`round`,margin:{top:0,bottom:1}});console.log(e),console.log(t)}if(u.length===0){console.log(J(t?G.yellow(`No tasks with status '${t}' found`):G.yellow(`No tasks found`),{padding:1,borderColor:`yellow`,borderStyle:`round`}));return}let ge=i?10:7,ve=100-ge-15-12-20-10,ye=V-10,xe=Math.floor(ge/100*ye),U=Math.floor(15/100*ye),Ce=Math.floor(12/100*ye),we=Math.floor(20/100*ye),Te=Math.floor(10/100*ye),W=Math.floor(ve/100*ye),Ee=new Oe({head:[G.cyan.bold(`ID`),G.cyan.bold(`Title`),G.cyan.bold(`Status`),G.cyan.bold(`Priority`),G.cyan.bold(`Dependencies`),G.cyan.bold(`Complexity`)],colWidths:[xe,W,U,Ce,we,Te],style:{head:[],border:[],compact:!1},wordWrap:!0,wrapOnWordBoundary:!0});u.forEach(e=>{let t=`None`;t=e.dependencies&&e.dependencies.length>0?fe(e.dependencies,o.tasks,!0,l):z.muted(`None`);let n=e.title.replace(/\n/g,` `),r={high:G.red,medium:G.yellow,low:z.muted}[e.priority||`medium`]||G.reset,a=Se(e.status,!0);Ee.push([e.id.toString(),P(n,W-3),a,r(P(e.priority||`medium`,Ce-2)),t,e.complexityScore?be(e.complexityScore):z.muted(`N/A`)]),i&&e.subtasks&&e.subtasks.length>0&&e.subtasks.forEach(t=>{let n=`None`;t.dependencies&&t.dependencies.length>0&&(n=t.dependencies.map(t=>{if(typeof t==`number`&&t<100){let n=e.subtasks.find(e=>e.id===t);if(n){let r=n.status===`done`||n.status===`completed`,i=n.status===`in-progress`;return r?G.green.bold(`${e.id}.${t}`):i?z.active.bold(`${e.id}.${t}`):G.red.bold(`${e.id}.${t}`)}}let n=o.tasks.find(e=>e.id===t);if(n){f(n,l);let e=n.status===`done`||n.status===`completed`,r=n.status===`in-progress`;return e?G.green.bold(`${t}`):r?z.active.bold(`${t}`):G.red.bold(`${t}`)}return G.cyan(t.toString())}).join(`, `)||z.muted(`None`)),Ee.push([`${e.id}.${t.id}`,G.dim(`└─ ${P(t.title,W-5)}`),Se(t.status,!0),G.dim(`-`),n,t.complexityScore?z.muted(`${t.complexityScore}`):z.muted(`N/A`)])})});try{console.log(Ee.toString())}catch(e){d(`error`,`Error rendering table: ${e.message}`),console.log(G.yellow(`
35
- Falling back to simple task list due to terminal width constraints:`)),u.forEach(e=>{console.log(`${G.cyan(e.id)}: ${G.reset(e.title)} - ${Se(e.status)}`)})}t&&(console.log(G.yellow(`\nFiltered by status: ${t}`)),console.log(G.yellow(`Showing ${u.length} of ${p} tasks`)));let K={high:G.red.bold,medium:G.yellow,low:z.muted};if(R){let e=``,t=o.tasks.find(e=>String(e.id)===String(R.id));t&&t.subtasks&&t.subtasks.length>0&&(e=`\n\n${G.bold(`Subtasks:`)}\n`,e+=t.subtasks.map(e=>{f(e,l);let n=e.status||`pending`,r={done:G.green,completed:G.green,pending:G.yellow,"in-progress":G.cyan,deferred:z.muted,blocked:G.red,cancelled:z.muted}[n.toLowerCase()]||G.reset;return`${G.cyan(`${t.id}.${e.id}`)} [${r(n)}] ${e.title}`}).join(`
36
- `));let n=le(R.id,R.status,!!t?.subtasks?.length).slice(0,2).map(e=>`${G.cyan(`Next step:`)} ${G.yellow(e.command)} ${z.muted(e.description)}`).join(`
37
- `);console.log(J(z.heading(`Next task: #${R.id} - ${R.title}`)+`
38
-
39
- ${G.reset(`Priority:`)} ${K[R.priority||`medium`](R.priority||`medium`)} ${G.reset(`Status:`)} ${Se(R.status,!0)}\n${G.reset(`Dependencies:`)} ${R.dependencies&&R.dependencies.length>0?fe(R.dependencies,o.tasks,!0,l):z.muted(`None`)}\n\n${G.reset(`Description:`)} ${jt(R,o.tasks)}`+e+`
40
-
41
- ${n}\n${G.cyan(`View details:`)} ${G.yellow(`taskgraph show ${R.id}`)}`,{padding:{left:2,right:2,top:1,bottom:1},borderColor:_e,borderStyle:`round`,margin:{top:1,bottom:1},title:`Next task`,titleAlignment:`center`,width:V-4,fullscreen:!1}))}else console.log(J(z.heading(`No eligible next task found`)+`
42
-
43
- All pending tasks have dependencies that are not yet completed, or all tasks are done.`,{padding:1,borderColor:_e,borderStyle:`round`,margin:{top:1,bottom:1},title:`Next task`,titleAlignment:`center`,width:V-4}));console.log(J(G.bold(`Suggested Next Steps:`)+`
44
-
45
- ${G.cyan(`1.`)} Run ${G.yellow(`taskgraph next`)} to see what to work on next\n${G.cyan(`2.`)} Run ${G.yellow(`taskgraph expand --id=<id>`)} to break down a task into subtasks\n${G.cyan(`3.`)} Run ${G.yellow(`taskgraph set-status --id=<id> --status=done`)} to mark a task as complete`,{padding:1,...j,borderStyle:`round`,margin:{top:1}}))}catch(e){if(d(`error`,`Error listing tasks: ${e.message}`),a===`json`)throw{code:`TASK_LIST_ERROR`,message:e.message,details:e.stack};console.error(G.red(`Error: ${e.message}`)),process.exit(1)}}function jt(e,t){if(!e)return`N/A`;if(e.parentId){let n=t.find(t=>t.id===e.parentId);return n?.subtasks?.find(t=>`${n.id}.${t.id}`===e.id)?.description||`No description available.`}return t.find(t=>String(t.id)===String(e.id))?.description||`No description available.`}function Mt(e,t,n){let{totalTasks:r,completedTasks:i,completionPercentage:a,doneCount:o,inProgressCount:s,pendingCount:c,blockedCount:l,deferredCount:u,cancelledCount:d,totalSubtasks:f,completedSubtasks:p,subtaskCompletionPercentage:m,inProgressSubtasks:h,pendingSubtasks:g,blockedSubtasks:_,deferredSubtasks:v,cancelledSubtasks:y,tasksWithNoDeps:b,tasksReadyToWork:x,tasksWithUnsatisfiedDeps:S,mostDependedOnTask:C,mostDependedOnTaskId:w,maxDependents:T,avgDependenciesPerTask:E,complexityReport:D,withSubtasks:O,nextItem:k}=n,A=``,j=(e,t=20)=>{let n=Math.round(e/100*t),r=t-n;return`█`.repeat(n)+`░`.repeat(r)},M=j(a,20),N=j(m,20);A+=`| Project Dashboard | |
46
- `,A+=`| :- |:-|
47
- `,A+=`| Task Progress | ${M} ${Math.round(a)}% |\n`,A+=`| Done | ${o} |\n`,A+=`| In Progress | ${s} |\n`,A+=`| Pending | ${c} |\n`,A+=`| Deferred | ${u} |\n`,A+=`| Cancelled | ${d} |\n`,A+=`|-|-|
48
- `,A+=`| Subtask Progress | ${N} ${Math.round(m)}% |\n`,A+=`| Completed | ${p} |\n`,A+=`| In Progress | ${h} |\n`,A+=`| Pending | ${g} |\n`,A+=`
49
-
50
- `,A+=`| ID | Title | Status | Priority | Dependencies | Complexity |
51
- `,A+=`| :- | :- | :- | :- | :- | :- |
52
- `;let P=e=>{switch(e){case`done`:case`completed`:return`✓&nbsp;done`;case`in-progress`:return`►&nbsp;in-progress`;case`pending`:return`○&nbsp;pending`;case`blocked`:return`⭕&nbsp;blocked`;case`deferred`:return`x&nbsp;deferred`;case`cancelled`:return`x&nbsp;cancelled`;case`review`:return`?&nbsp;review`;default:return e||`pending`}},ee=(e,t)=>!e||e.length===0?`None`:e.map(e=>(t.find(t=>t.id===e),e.toString())).join(`, `);return t.forEach(t=>{let n=t.title,r=P(t.status),i=t.priority||`medium`,a=ee(t.dependencies,e.tasks),o=t.complexityScore?`● ${t.complexityScore}`:`N/A`;A+=`| ${t.id} | ${n} | ${r} | ${i} | ${a} | ${o} |\n`,O&&t.subtasks&&t.subtasks.length>0&&t.subtasks.forEach(n=>{let r=`${n.title}`,i=P(n.status),a=ee(n.dependencies,e.tasks),o=n.complexityScore?n.complexityScore.toString():`N/A`;A+=`| ${t.id}.${n.id} | ${r} | ${i} | - | ${a} | ${o} |\n`})}),A}function Nt(e){if(!e||e.length===0)return``;if(e.length>5){let t=e.slice(0,5).join(`,`),n=e.length-5;return` → ${G.cyan(t)}${z.muted(`... (+`+n+` more)`)}`}return` → ${G.cyan(e.join(`,`))}`}function Pt(e,t=50){let n=e.status||`pending`,r=e.priority||`medium`,i=P(e.title||`Untitled`,t),a=Se(n,!0),o={high:G.red,medium:G.yellow,low:z.muted}[r]||G.reset,s=Nt(e.dependencies);return`${G.cyan(e.id)} ${a} ${G.reset(i)} ${o(`(`+r+`)`)}${s}`}function Ft(e,t,n=47){let r=e.status||`pending`,i=P(e.title||`Untitled`,n),a=Se(r,!0),o=Nt(e.dependencies);return` ${G.cyan(t+`.`+e.id)} ${a} ${G.dim(i)}${o}`}function It(e,t){if(e.length===0){console.log(`No tasks found`);return}let n=[];e.forEach(e=>{n.push(Pt(e)),t&&e.subtasks&&e.subtasks.length>0&&e.subtasks.forEach(t=>{n.push(Ft(t,e.id))})}),console.log(n.join(`
53
- `))}function Lt(e,t,n,r){c(e,l(e.metadata,t,n,r))}function Rt(e,n,r,i){return t(e,n,r,i)}function zt(e,t,n={}){return T(e,t,{...n,direction:`forward`,logger:{warn:console.warn}})}var Z=class extends Error{constructor(e,t,n={}){super(t),this.name=`MoveTaskError`,this.code=e,this.data=n}};const Q={CROSS_TAG_DEPENDENCY_CONFLICTS:`CROSS_TAG_DEPENDENCY_CONFLICTS`,CANNOT_MOVE_SUBTASK:`CANNOT_MOVE_SUBTASK`,SOURCE_TARGET_TAGS_SAME:`SOURCE_TARGET_TAGS_SAME`,TASK_NOT_FOUND:`TASK_NOT_FOUND`,SUBTASK_NOT_FOUND:`SUBTASK_NOT_FOUND`,PARENT_TASK_NOT_FOUND:`PARENT_TASK_NOT_FOUND`,PARENT_TASK_NO_SUBTASKS:`PARENT_TASK_NO_SUBTASKS`,DESTINATION_TASK_NOT_FOUND:`DESTINATION_TASK_NOT_FOUND`,TASK_ALREADY_EXISTS:`TASK_ALREADY_EXISTS`,INVALID_MOVE:`INVALID_MOVE`,INVALID_TASKS_FILE:`INVALID_TASKS_FILE`,ID_COUNT_MISMATCH:`ID_COUNT_MISMATCH`,INVALID_SOURCE_TAG:`INVALID_SOURCE_TAG`,INVALID_TARGET_TAG:`INVALID_TARGET_TAG`};function Bt(e){if(e==null)return e;if(typeof e==`number`)return Number.isFinite(e)?e:null;if(typeof e==`string`){let t=e.trim();if(t===``)return null;let n=t.includes(`.`)?t.split(`.`)[0]:t,r=parseInt(n,10);return Number.isFinite(r)?r:null}return null}async function Vt(e,t,n,r=!1,i={}){let{projectRoot:a,tag:o}=i,s=t.split(`,`).map(e=>e.trim()),c=n.split(`,`).map(e=>e.trim());if(s.length!==c.length)throw new Z(Q.ID_COUNT_MISMATCH,`Number of source IDs (${s.length}) must match number of destination IDs (${c.length})`);if(s.length>1){let t=[];for(let n=0;n<s.length;n++){let r=await Vt(e,s[n],c[n],!1,i);t.push(r)}return{message:`Successfully moved ${s.length} tasks/subtasks`,moves:t}}let l=M(e,a,o);if(l&&l._rawTaggedData&&(l=l._rawTaggedData),!l||!l[o]||!Array.isArray(l[o].tasks))throw new Z(Q.INVALID_TASKS_FILE,`Invalid tasks file or tag "${o}" not found at ${e}`);let u=l[o].tasks;d(`debug`,`Moving task/subtask ${t} to ${n} (tag: ${o})`);let f=t.includes(`.`),p=n.includes(`.`),m;return m=f&&p?Ht(u,t,n):f&&!p?Ut(u,t,n):!f&&p?Wt(u,t,n):Gt(u,t,n),l[o].tasks=u,E(e,l,i.projectRoot,o),m}function Ht(e,t,n){let[r,i]=t.split(`.`).map(e=>parseInt(e,10)),[a,o]=n.split(`.`).map(e=>parseInt(e,10)),s=e.find(e=>e.id===r),c=e.find(e=>e.id===a);if(!s)throw new Z(Q.PARENT_TASK_NOT_FOUND,`Source parent task with ID ${r} not found`);if(!c)throw new Z(Q.PARENT_TASK_NOT_FOUND,`Destination parent task with ID ${a} not found`);s.subtasks||=[],c.subtasks||=[];let l=s.subtasks.findIndex(e=>e.id===i);if(l===-1)throw new Z(Q.SUBTASK_NOT_FOUND,`Source subtask ${t} not found`);let u=s.subtasks[l];if(r===a){if(c.subtasks.length>0){let e=c.subtasks.findIndex(e=>e.id===o);if(e!==-1){s.subtasks.splice(l,1);let t=l<e?e-1:e;c.subtasks.splice(t+1,0,u)}else s.subtasks.splice(l,1),c.subtasks.push(u)}else s.subtasks.splice(l,1),c.subtasks.push(u)}else{if(c.subtasks.some(e=>e.id===o))throw new Z(Q.TASK_ALREADY_EXISTS,`Subtask ${a}.${o} already exists. Use a different destination ID`);Kt(u,s,l,c,o,e)}return{message:`Moved subtask ${t} to ${n}`,movedItem:u}}function Ut(e,t,n){let[r,i]=t.split(`.`).map(e=>parseInt(e,10)),a=parseInt(n,10),o=e.find(e=>e.id===r);if(!o)throw new Z(Q.PARENT_TASK_NOT_FOUND,`Source parent task with ID ${r} not found`);if(!o.subtasks)throw new Z(Q.PARENT_TASK_NO_SUBTASKS,`Source parent task ${r} has no subtasks`);let s=o.subtasks.findIndex(e=>e.id===i);if(s===-1)throw new Z(Q.SUBTASK_NOT_FOUND,`Source subtask ${t} not found`);let l=o.subtasks[s];if(e.find(e=>e.id===a))throw new Z(Q.TASK_ALREADY_EXISTS,`Cannot move to existing task ID ${a}. Choose a different ID or use subtask destination.`);let u=je(l,o.id,void 0),d={id:a,title:l.title,description:l.description,status:l.status||`pending`,dependencies:u.dependencies,priority:l.priority||`medium`,details:l.details||``,testStrategy:l.testStrategy||``,subtasks:[]};c(d,u.metadata),o.subtasks.splice(s,1),Ne(e,`${o.id}.${i}`,a);let f=e.findIndex(e=>e.id>a);return f===-1?e.push(d):e.splice(f,0,d),{message:`Converted subtask ${t} to task ${n}`,movedItem:d}}function Wt(e,t,n){let r=parseInt(t,10),[i,a]=n.split(`.`).map(e=>parseInt(e,10)),o=e.findIndex(e=>e.id===r),s=e.find(e=>e.id===i);if(o===-1)throw new Z(Q.TASK_NOT_FOUND,`Source task with ID ${r} not found`);if(!s)throw new Z(Q.PARENT_TASK_NOT_FOUND,`Destination parent task with ID ${i} not found`);let l=e[o];if(i===r)throw new Z(Q.INVALID_MOVE,`Cannot move task ${r} inside itself`);if(l.subtasks?.length>0)throw new Z(Q.INVALID_MOVE,`Task ${r} has subtasks and cannot become a subtask. Move or remove its subtasks first`);if(s.subtasks?.some(e=>e.id===a))throw new Z(Q.TASK_ALREADY_EXISTS,`Subtask ${i}.${a} already exists. Use a different destination ID`);s.subtasks||=[];let u=Me(l,s.id),d={id:a,title:l.title,description:l.description,status:l.status||`pending`,dependencies:u.dependencies,details:l.details||``,testStrategy:l.testStrategy||``};c(d,u.metadata);let f=-1;s.subtasks.length>0&&(f=s.subtasks.findIndex(e=>e.id===a),f===-1&&(f=s.subtasks.length-1));let p=f===-1?0:f+1;return s.subtasks.splice(p,0,d),e.splice(o,1),Ne(e,String(r),`${s.id}.${a}`),{message:`Converted task ${t} to subtask ${n}`,movedItem:d}}function Gt(e,t,n){let r=parseInt(t,10),i=parseInt(n,10),a=e.findIndex(e=>e.id===r);if(a===-1)throw new Z(Q.TASK_NOT_FOUND,`Source task with ID ${r} not found`);let o=e[a],s=e.findIndex(e=>e.id===i);if(s!==-1)throw e[s],new Z(Q.TASK_ALREADY_EXISTS,`Task with ID ${i} already exists. Use a different destination ID.`);return qt(e,a,o,i)}function Kt(e,t,n,r,i,a){let o=parseInt(i,10),s=je(e,t.id,r.id),l={...e,id:o,dependencies:s.dependencies};c(l,s.metadata),r.subtasks||=[];let u=-1;r.subtasks.length>0&&(u=r.subtasks.findIndex(e=>e.id===o),u===-1&&(u=r.subtasks.length-1));let d=u===-1?0:u+1;return r.subtasks.splice(d,0,l),t.subtasks.splice(n,1),Ne(a,`${t.id}.${e.id}`,`${r.id}.${o}`),l}function qt(t,n,r,i){let a=t.findIndex(e=>e.id===i),o={...r,id:i},s=String(r.id),l=String(i);t.forEach(t=>{t.dependencies?.some(e=>String(e)===s)&&(t.dependencies=t.dependencies.map(e=>String(e)===s?i:e),Lt(t,s,l)),t.subtasks&&t.subtasks.forEach(n=>{let r=n=>e(t.id,n)===s;n.dependencies?.some(r)&&(n.dependencies=n.dependencies.map(e=>r(e)?l:e),Lt(n,s,l,t.id))})}),Array.isArray(o.subtasks)&&o.subtasks.forEach(e=>{if(Array.isArray(e.dependencies)){let t=e=>{if(typeof e==`string`&&e.includes(`.`)){let[t,n]=e.split(`.`);if(parseInt(t,10)===r.id)return`${i}.${n}`}return e};e.metadata&&c(e,Rt(e,r.id,i,t)),e.dependencies=e.dependencies.map(t)}}),t.splice(n,1);let u=n<a?a-1:a;return u>=0&&u<t.length?t[u]=o:t.push(o),d(`debug`,`Moved task ${r.id} to new ID ${i}`),{message:`Moved task ${r.id} to new ID ${i}`,movedItem:o}}function Jt(e){let t=[];for(let n in e)if(Object.prototype.hasOwnProperty.call(e,n)&&e[n]&&Array.isArray(e[n].tasks)){let r=e[n].tasks.map(e=>({...e,tag:n}));t=t.concat(r)}return t}async function Yt(e,t,n,r,i){let{projectRoot:a}=i,o=M(e,a,n);if(o&&o._rawTaggedData&&(o=o._rawTaggedData),!o||!o[n]||!Array.isArray(o[n].tasks))throw new Z(Q.INVALID_SOURCE_TAG,`Source tag "${n}" not found or invalid`);o[r]||(o[r]={tasks:[]},d(`info`,`Created new tag "${r}"`));let s=t.map(e=>String(e)),c=o[n].tasks.filter(e=>{let t=String(e.id);return s.includes(t)});return t.forEach(e=>{et(e,n,r)}),{rawData:o,sourceTasks:c}}async function Xt(e){let{rawData:t,sourceTasks:n}=e;return{rawData:t,sourceTasks:n,allTasks:Jt(t)}}async function Zt(e,t,n,r,i,o){let{withDependencies:s=!1,ignoreDependencies:l=!1}=n,u=Array.isArray(t)?t.filter(e=>e&&e.tag===i):[];if(s){let t=zt(e,u,{maxDepth:100,includeSelf:!1}),n=new Set(u.map(e=>typeof e.id==`string`?parseInt(e.id,10):e.id)),i=t.filter(e=>{let t=Bt(e);return Number.isFinite(t)&&n.has(t)}),a=[.../* @__PURE__ */ new Set([...r,...i])];return d(`info`,`Moving ${a.length} tasks (including dependencies): ${a.join(`, `)}`),{tasksToMove:a,dependencyResolution:{type:`with-dependencies`,dependentTasks:i}}}let f=$e(e,i,o,t);if(f.length>0){if(l)return e.forEach(e=>{let n=u,r=Array.isArray(t)?t.filter(e=>e&&e.tag===o):[];e.dependencies=e.dependencies.filter(e=>{let t=Bt(e);return Number.isFinite(t)&&n.some(e=>e.id===t)?!1:(Number.isFinite(t)&&r.some(e=>e.id===t),!0)}),e.metadata&&c(e,a(e))}),d(`warn`,`Removed ${f.length} cross-tag dependencies`),{tasksToMove:r,dependencyResolution:{type:`ignored-dependencies`,conflicts:f}};throw new Z(Q.CROSS_TAG_DEPENDENCY_CONFLICTS,`Cannot move tasks: ${f.length} cross-tag dependency conflicts found`,{conflicts:f,sourceTag:i,targetTag:o,taskIds:r})}return{tasksToMove:r,dependencyResolution:{type:`no-conflicts`}}}async function Qt(e,t,n,r,i,a){let{projectRoot:o}=i,s=[];for(let i of e){let e=typeof i==`string`?parseInt(i,10):i,a=r[t].tasks.findIndex(t=>t.id===e);if(a===-1)throw new Z(Q.TASK_NOT_FOUND,`Task ${i} not found in source tag "${t}"`);let o=r[t].tasks[a];if(r[n].tasks.findIndex(t=>t.id===e)!==-1)throw new Z(Q.TASK_ALREADY_EXISTS,`Task ${i} already exists in target tag "${n}"`,{conflictingId:e,targetTag:n,suggestions:[`Choose a different target tag without conflicting IDs`,`Move a different set of IDs (avoid existing ones)`,`If needed, move within-tag to a new ID first, then cross-tag move`]});r[t].tasks.splice(a,1);let c=tn(o,t,n);r[n].tasks.push(c),s.push({id:i,fromTag:t,toTag:n}),d(`debug`,`Moved task ${i} from "${t}" to "${n}"`)}return{rawData:r,movedTasks:s}}async function $t(e,t,n,r,i,a){let{projectRoot:o}=n,{rawData:s,movedTasks:c}=e;E(t,s,o,null);let l={message:`Successfully moved ${c.length} tasks from "${r}" to "${i}"`,movedTasks:c};return a&&a.type===`ignored-dependencies`&&(l.tips=[`Run "taskgraph validate-dependencies" to check for dependency issues.`,`Run "taskgraph fix-dependencies" to automatically repair dangling dependencies.`]),l}async function en(e,t,n,r,i={},a={}){let{rawData:o,sourceTasks:s,allTasks:c}=await Xt(await Yt(e,t,n,r,a)),{tasksToMove:l,dependencyResolution:u}=await Zt(s,c,i,t,n,r);return await $t(await Qt(l,n,r,o,a,e),e,a,n,r,u)}function tn(e,t,n){return e.tag=n,e.metadata||={},e.metadata.moveHistory||(e.metadata.moveHistory=[]),e.metadata.moveHistory.push({fromTag:t,toTag:n,timestamp:(/* @__PURE__ */ new Date()).toISOString()}),e}var nn=class e extends Error{constructor(t,n){super(t),this.name=`StreamingError`,this.code=n,Error.captureStackTrace&&Error.captureStackTrace(this,e)}};const rn={NOT_ASYNC_ITERABLE:`STREAMING_NOT_SUPPORTED`,STREAM_PROCESSING_FAILED:`STREAM_PROCESSING_FAILED`,STREAM_NOT_ITERABLE:`STREAM_NOT_ITERABLE`,BUFFER_SIZE_EXCEEDED:`BUFFER_SIZE_EXCEEDED`};var an=class e{static async withTimeout(e,t,n=`Operation`){let r,i=new Promise((e,i)=>{r=setTimeout(()=>{i(new nn(`${n} timed out after ${t/1e3} seconds`,rn.STREAM_PROCESSING_FAILED))},t)});try{let t=await Promise.race([e,i]);return clearTimeout(r),t}catch(e){throw clearTimeout(r),e}}static async withSoftTimeout(e,t,n=void 0){let r,i=new Promise(e=>{r=setTimeout(()=>{e(n)},t)});try{let t=await Promise.race([e,i]);return clearTimeout(r),t}catch{return clearTimeout(r),n}}static createController(t,n=`Operation`){return{timeoutMs:t,operationName:n,async wrap(r,i=null){let a=i?`${n} - ${i}`:n;return e.withTimeout(r,t,a)},async wrapSoft(n,r=void 0){return e.withSoftTimeout(n,t,r)}}}static isTimeoutError(e){return e instanceof nn&&e.code===rn.STREAM_PROCESSING_FAILED&&e.message.includes(`timed out`)}},on=class e{constructor(e,t=`ms`){this.milliseconds=this._toMilliseconds(e,t)}static milliseconds(t){return new e(t,`ms`)}static seconds(t){return new e(t,`s`)}static minutes(t){return new e(t,`m`)}static hours(t){return new e(t,`h`)}get seconds(){return this.milliseconds/1e3}get minutes(){return this.milliseconds/6e4}get hours(){return this.milliseconds/36e5}toString(){return this.milliseconds<1e3?`${this.milliseconds}ms`:this.milliseconds<6e4?`${this.seconds}s`:this.milliseconds<36e5?`${Math.floor(this.minutes)}m ${Math.floor(this.seconds%60)}s`:`${Math.floor(this.hours)}h ${Math.floor(this.minutes%60)}m`}_toMilliseconds(e,t){return e*({ms:1,s:1e3,m:6e4,h:36e5}[t]||1)}};const sn=K.object({id:K.number(),title:K.string().min(1),description:K.string().min(1),details:K.string(),testStrategy:K.string(),priority:K.enum(nt),dependencies:K.array(K.number()),status:K.string()}),cn=K.object({tasks:K.array(sn),metadata:K.union([K.object({projectName:K.string(),totalTasks:K.number(),sourceFile:K.string(),generatedAt:K.string()}),K.null()]).default(null)});var ln=class{constructor(e,t,n,r={}){this.prdPath=e,this.tasksPath=t,this.numTasks=n,this.force=r.force||!1,this.append=r.append||!1,this.research=r.research||!1,this.reportProgress=r.reportProgress,this.mcpLog=r.mcpLog,this.session=r.session,this.projectRoot=r.projectRoot,this.tag=r.tag,this.streamingTimeout=r.streamingTimeout||on.seconds(180).milliseconds,this.targetTag=this.tag||x(this.projectRoot)||`master`,this.isMCP=!!this.mcpLog,this.outputFormat=this.isMCP&&!this.reportProgress?`json`:`text`,this.useStreaming=!1}hasCodebaseAnalysis(){return p(this.research,this.projectRoot,this.session)}},un=class{constructor(e,t){this.isMCP=!!e,this.outputFormat=this.isMCP&&!t?`json`:`text`,this.logFn=e||{info:(...e)=>d(`info`,...e),warn:(...e)=>d(`warn`,...e),error:(...e)=>d(`error`,...e),debug:(...e)=>d(`debug`,...e),success:(...e)=>d(`success`,...e)}}report(e,t=`info`){this.logFn&&typeof this.logFn[t]==`function`?this.logFn[t](e):!v()&&this.outputFormat===`text`&&d(t,e)}};function dn(e){return`${Math.floor(e/60)}m ${Math.floor(e%60).toString().padStart(2,`0`)}s`}const fn={BAR_WIDTH:40,TABLE_COL_WIDTHS:[28,50],DEFAULT_MODEL:`Default`,DEFAULT_TEMPERATURE:.7},$={HIGH:`high`,MEDIUM:`medium`,LOW:`low`},pn={[$.HIGH]:G.red,[$.MEDIUM]:G.yellow,[$.LOW]:C.muted},mn={main:{padding:{top:1,bottom:1,left:2,right:2},margin:{top:0,bottom:0},borderColor:L,borderStyle:`round`},summary:{padding:{top:1,right:1,bottom:1,left:1},borderColor:L,borderStyle:`round`,margin:{top:1,right:1,bottom:1,left:0}},warning:{padding:1,borderColor:`yellow`,borderStyle:`round`,margin:{top:1,bottom:1}},nextSteps:{padding:1,borderColor:`cyan`,borderStyle:`round`,margin:{top:1,right:0,bottom:1,left:0}}};function hn({prdFilePath:e,outputPath:t,numTasks:n,model:r,temperature:i,append:a,research:o}){let s=a?`Appending`:`Generating`,c=`Model: ${r} | Temperature: ${i}`;return o&&(c+=` | ${G.cyan.bold(`🔬 Research Mode`)}`),G.bold(`🤖 Parsing PRD and ${s} Tasks`)+`
54
- `+G.dim(c)+`
55
-
56
- `+C.brand(`Input: ${e}`)+`
57
- `+C.brand(`Output: ${t}`)+`
58
- `+C.brand(`Tasks to ${a?`Append`:`Generate`}: ${n}`)}function gn(e){console.log(J(e,mn.main))}function _n(e,t){console.log(G.yellow.bold(`📝 Append mode`)+` - Adding to ${e} existing tasks (next ID: ${t})`)}function vn(e){let t=G.red.bold(`⚠️ Force flag enabled`);return e?`${t} - Will overwrite if conflicts occur`:`${t} - Overwriting existing tasks`}function yn({prdFilePath:e,outputPath:t,numTasks:n,model:r=fn.DEFAULT_MODEL,temperature:i=fn.DEFAULT_TEMPERATURE,append:a=!1,research:o=!1,force:s=!1,existingTasks:c=[],nextId:l=1}){if(!e||typeof e!=`string`||e.trim()===``)throw Error(`prdFilePath is required and must be a non-empty string`);if(!t||typeof t!=`string`||t.trim()===``)throw Error(`outputPath is required and must be a non-empty string`);gn(hn({prdFilePath:e,outputPath:t,numTasks:n,model:r,temperature:i,append:a,research:o})),(a||s)&&(a&&_n(c.length,l),s&&console.log(vn(a)),console.log())}function bn(e,t){let n={};return Object.values($).forEach(r=>{let i=e[r]||0;n[r]={count:i,percentage:t>0?Math.round(i/t*100):0}}),n}function xn(e,t){let n=fn.BAR_WIDTH,r={};if(t===0)return Object.values($).forEach(e=>{r[e]=0}),r;let i={};Object.values($).forEach(r=>{i[r]=e[r].count/t*n}),Object.values($).forEach(e=>{r[e]=Math.floor(i[e])}),Object.values($).forEach(t=>{e[t].count>0&&r[t]===0&&(r[t]=1)});let a=n-Object.values(r).reduce((e,t)=>e+t,0);if(a>0){let e=Object.values($).map(e=>({priority:e,decimal:i[e]-Math.floor(i[e])})).sort((e,t)=>t.decimal-e.decimal);for(let t=0;t<a&&t<e.length;t++)r[e[t].priority]++}return r}function Sn(e){let t=``;t+=pn[$.HIGH](`█`.repeat(e[$.HIGH])),t+=pn[$.MEDIUM](`█`.repeat(e[$.MEDIUM])),t+=pn[$.LOW](`█`.repeat(e[$.LOW]));let n=Object.values(e).reduce((e,t)=>e+t,0);return n<fn.BAR_WIDTH&&(t+=C.muted(`░`.repeat(fn.BAR_WIDTH-n))),t}function Cn(e){let t=[];return Object.entries($).forEach(([n,r])=>{let i=e[r],a=pn[r],o=n.charAt(0)+n.slice(1).toLowerCase();t.push(`${a.bold(i.count)} ${a(o)} (${i.percentage}%)`)}),[G.cyan(`Priority distribution:`),t.join(` · `)]}function wn(e){let{totalTasks:t,taskPriorities:n={},prdFilePath:r,outputPath:i,elapsedTime:a,usedFallback:o=!1,actionVerb:s=`generated`}=e,c=dn(a),l=new Oe({chars:{top:``,"top-mid":``,"top-left":``,"top-right":``,bottom:``,"bottom-mid":``,"bottom-left":``,"bottom-right":``,left:``,"left-mid":``,mid:``,"mid-mid":``,right:``,"right-mid":``,middle:` `},style:{border:[],"padding-left":2},colWidths:fn.TABLE_COL_WIDTHS});if(l.push([G.cyan(`Total tasks ${s}:`),G.bold(t)],[G.cyan(`Processing time:`),G.bold(c)]),n&&Object.keys(n).length>0){let e=bn(n,t),r=Cn(e);l.push(r);let i=Sn(xn(e,t));l.push([G.cyan(`Distribution:`),i])}l.push([G.cyan(`PRD source:`),G.italic(r)],[G.cyan(`Tasks file:`),G.italic(i)]),o&&l.push([G.yellow(`Fallback parsing:`),G.yellow(`✓ Used fallback parsing`)]);let u=[G.bold.underline(`PRD Parsing Complete - Tasks ${s.charAt(0).toUpperCase()+s.slice(1)}`),``,l.toString()].join(`
59
- `);console.log(J(u,mn.summary)),o&&Tn(),En()}function Tn(){let e=G.yellow.bold(`⚠️ Fallback Parsing Used`)+`
60
-
61
- `+C.text(`The system used fallback parsing to complete task generation.`)+`
62
- `+C.text(`This typically happens when streaming JSON parsing is incomplete.`)+`
63
- `+C.text(`Your tasks were successfully generated, but consider:`)+`
64
- `+C.text(`• Reviewing task completeness`)+`
65
- `+C.text(`• Checking for any missing details`)+`
66
-
67
- `+C.text(`This is normal and usually doesn't indicate any issues.`);console.log(J(e,mn.warning))}function En(){let e=C.text.bold(`Next Steps:`)+`
68
-
69
- ${G.cyan(`1.`)} Run ${G.yellow(`taskgraph list`)} to view all tasks\n${G.cyan(`2.`)} Run ${G.yellow(`taskgraph expand --id=<id>`)} to break down a task into subtasks\n${G.cyan(`3.`)} Run ${G.yellow(`taskgraph analyze-complexity`)} to analyze task complexity`;console.log(J(e,mn.nextSteps))}function Dn(e){if(typeof e!=`string`)return null;let t=e.indexOf(`{`);if(t<0)return null;let n=0,r=!1,i=!1;for(let a=t;a<e.length;a++){let o=e[a];if(r)i?i=!1:o===`\\`?i=!0:o===`"`&&(r=!1);else if(o===`"`)r=!0;else if(o===`{`)n++;else if(o===`}`&&(n--,n===0))return e.slice(t,a+1)}return null}function On(e){let t=Dn(e);if(!t)return null;try{let e=cn.safeParse(JSON.parse(t));return e.success?e.data:null}catch{return null}}function kn(e){return Math.ceil(e.length/4)}function An(e){let t=q.readFileSync(e,`utf8`);if(!t)throw Error(`Input file ${e} is empty or could not be read.`);return t}function jn(e,t){let n=[],r=1,i=Mn(e);return i[t]?.tasks&&Array.isArray(i[t].tasks)&&(n=i[t].tasks,n.length>0&&(r=Math.max(...n.map(e=>e.id||0))+1)),{existingTasks:n,nextId:r}}function Mn(e){if(!q.existsSync(e))return{};let t=q.readFileSync(e,`utf8`);if(t.trim()===``)return{};try{return JSON.parse(t)}catch(t){throw Error(`${e} is not valid JSON (${t.message}). Fix or remove the file, then run this again`)}}function Nn({existingTasks:e,targetTag:t,append:n,force:r,isMCP:i,logger:a}){if(!(e.length>0))a.report(`Tag '${t}' is empty or doesn't exist. Creating/updating tag with new tasks.`,`debug`);else if(n)a.report(`Append mode enabled. Found ${e.length} existing tasks in tag '${t}'.`,`info`);else{if(!r){let n=`Tag '${t}' already contains ${e.length} tasks. Use --force to overwrite or --append to add to existing tasks.`;if(a.report(n,`error`),i)throw Error(n);console.error(G.red(n)),process.exit(1)}a.report(`Force flag enabled. Overwriting existing tasks in tag '${t}'.`,`debug`)}}function Pn(e,t,n,r){Fn(e,t);let a=t,o=/* @__PURE__ */ new Map,s=e.map(e=>{let t=a++;return o.set(e.id,t),{...e,id:t,status:e.status||`pending`,priority:e.priority||r,dependencies:Array.isArray(e.dependencies)?e.dependencies:[],subtasks:e.subtasks||[],title:e.title||``,description:e.description||``,details:e.details||``,testStrategy:e.testStrategy||``}});return s.forEach(e=>{e.dependencies=e.dependencies.map(e=>o.get(e)).filter(t=>t!=null&&t<e.id&&(g(n,t)||s.some(e=>e.id===t))),c(e,i(e))}),s}function Fn(e,t=1){if(!Array.isArray(e)||e.length===0)return;let n=e.map(e=>e.id);if(n.some(e=>!Number.isInteger(e)||e<1))throw Error(`PRD tasks must use sequential positive integer IDs starting at 1.`);let r=new Set(n);if(r.size!==n.length)throw Error(`PRD task IDs must be unique and sequential starting at 1.`);let i=[...r].sort((e,t)=>e-t),a=i[0];if(a!==1&&a!==t)throw Error(`PRD task IDs must start at 1 or ${t} and be sequential.`);for(let e=0;e<i.length;e+=1)if(i[e]!==a+e)throw Error(`PRD task IDs must be a contiguous sequence starting at ${a}.`)}function In(e,t,n,r){let i=Ee.dirname(e);q.existsSync(i)||q.mkdirSync(i,{recursive:!0});let a=Mn(e);a[n]={tasks:t,metadata:{...a[n]?.metadata,created:a[n]?.metadata?.created||(/* @__PURE__ */ new Date()).toISOString(),updated:(/* @__PURE__ */ new Date()).toISOString(),description:`Tasks for ${n} context`}},b(a[n],{description:`Tasks for ${n} context`}),q.writeFileSync(e,JSON.stringify(a,null,2)),r.report(`Successfully saved ${t.length} tasks to ${e}`,`debug`)}async function Ln(e,t,n){let r=pe(),i=w(e.projectRoot)||`medium`;return r.loadPrompt(`parse-prd`,{research:e.research,numTasks:e.numTasks,nextId:n,prdContent:t,prdPath:e.prdPath,defaultTaskPriority:i,hasCodebaseAnalysis:e.hasCodebaseAnalysis(),projectRoot:e.projectRoot||``})}async function Rn({task:e,currentCount:t,totalTasks:n,estimatedTokens:r,progressTracker:i,reportProgress:a,priorityMap:o,defaultPriority:s,estimatedInputTokens:c}){let l=e.priority||s,u=o[l]||o.medium;if(i&&(i.addTaskLine(t,e.title,l),r&&i.updateTokens(c,r)),a)try{let i=r?Math.floor(r/n):0;await a({progress:t,total:n,message:`${u} Task ${t}/${n} - ${e.title} | ~Output: ${i} tokens`})}catch{}}async function zn({processedTasks:e,nextId:t,summary:n,prdPath:r,tasksPath:i,usedFallback:a,aiServiceResponse:o}){let s=(()=>{if(!Array.isArray(e)||e.length===0)return`task_${String(t).padStart(3,`0`)}.txt`;let n=e[0].id,r=e[e.length-1].id;return e.length===1?`task_${String(n).padStart(3,`0`)}.txt`:`task_${String(n).padStart(3,`0`)}.txt -> task_${String(r).padStart(3,`0`)}.txt`})();wn({totalTasks:e.length,taskPriorities:n.taskPriorities,prdFilePath:r,outputPath:i,elapsedTime:n.elapsedTime,usedFallback:a,taskFilesGenerated:s,actionVerb:n.actionVerb}),o?.telemetryData&&(o.mainResult?.usage&&await an.withSoftTimeout(o.mainResult.usage,1e3,void 0),H(o.telemetryData,`cli`))}function Bn({processedTasks:e,research:t,finalTasks:n,tasksPath:r,aiServiceResponse:i}){let a=Ee.relative(process.cwd(),r)||r,o=n.length>e.length?` · ${n.length} tasks in total`:``,s=t?` · research-backed`:``;console.log(C.muted(`Saved to ${a}${o}${s}`));let c=(e,t)=>`${G.yellow(e.padEnd(28))}${C.muted(t)}`;console.log(J(C.text.bold(`Next steps`)+`
70
-
71
- `+[c(`taskgraph next`,`the task to start with`),c(`taskgraph graph`,`how the tasks depend on each other`),c(`taskgraph expand --id=<id>`,`split a task into subtasks`)].join(`
72
- `),{padding:1,borderColor:`cyan`,borderStyle:`round`,margin:{top:1}})),i?.telemetryData&&H(i.telemetryData,`cli`)}async function Vn(e,t,n,r=1){let i=new un(e.mcpLog,e.reportProgress),a=kn(t.systemPrompt+t.userPrompt),o=e.outputFormat===`text`&&!e.isMCP&&!e.reportProgress;if(i.report(`Calling AI service to generate tasks from PRD${e.research?` with research-backed analysis`:``}...`,`debug`),o){let o=null;try{return o=de({prdName:Ee.basename(e.prdPath||`PRD`),numTasks:n,startId:r}),{...await Hn(e,t,o),estimatedInputTokens:a}}catch(t){if(ke.isInstance(t)&&!Gn(e))throw o?.fail(`Couldn't generate tasks`),t;o?.stop(),i.report(`Streaming task generation failed (${t.message}); retrying in one request`,`debug`),o?.printedCount&&console.log(`${G.yellow(`⚠`)} Live output stopped. Asking Claude again in one request; the final tasks may differ from the ones above.`)}}return{...await Wn(e,t,o),estimatedInputTokens:a}}async function Hn(e,t,n){let r=await Ce({...Kn(e,t)}),i=r?.mainResult,a=i?.partialObjectStream;if(!a)throw Error(`AI service did not return a stream`);for await(let e of a)n?.update(e);let o;try{o=await i.object}catch(e){if(o=On(e?.text),!o)throw e}if(!o||!Array.isArray(o.tasks))throw Error(`AI service returned unexpected data structure.`);return n?.succeed(o),r.telemetryData=await Un(i,r,e),{parsedTasks:o.tasks,aiServiceResponse:r}}async function Un(e,t,n){let r=t.telemetryData;if(!r?.userId)return r;try{let i=await e.usage;return await Te({userId:r.userId,commandName:`parse-prd`,providerName:t.providerName,modelId:t.modelId,inputTokens:i?.inputTokens??i?.promptTokens??0,outputTokens:i?.outputTokens??i?.completionTokens??0,cachedInputTokens:i?.inputTokenDetails?.cacheReadTokens??0,outputType:n.isMCP?`mcp`:`cli`})||r}catch{return r}}async function Wn(e,t,n){let r=n?U(`Parsing PRD and generating tasks…`):null;try{let n=await W(Kn(e,t)),i=qn(n?.mainResult);if(!i)throw Error(`AI service returned unexpected data structure after validation.`);return r&&xe(r,`${i.tasks.length} tasks generated`),{parsedTasks:i.tasks,aiServiceResponse:n}}catch(e){throw r&&V(r,`Couldn't generate tasks`),e}}function Gn(e){let t=e.projectRoot,n=e.research?oe(t):I(t);return[I(t),ae(t),oe(t)].filter(Boolean).some(e=>e!==n)}function Kn(e,t){return{role:e.research?`research`:`main`,session:e.session,projectRoot:e.projectRoot,schema:cn,objectName:`tasks_data`,systemPrompt:t.systemPrompt,prompt:t.userPrompt,commandName:`parse-prd`,outputType:e.isMCP?`mcp`:`cli`}}function qn(e){if(e&&typeof e==`object`){if(Array.isArray(e.tasks))return e;if(Array.isArray(e.object?.tasks))return e.object}return null}const[Jn,Yn,Xn]=nt,Zn=/* @__PURE__ */ new Map;var Qn=class{constructor(e,t,n,r=null){this.name=e,this.levels=t,this.colors=n,this.thresholds=r}getColor(e){return this.colors[e]||C.muted}getLevelFromScore(e){if(!this.thresholds)throw Error(`${this.name} does not support score-based levels`);return e>=7?this.levels[0]:e<=3?this.levels[2]:this.levels[1]}};const $n={cli:{filled:`●`,empty:`○`},statusBar:{high:`⋮`,medium:`:`,low:`.`},mcp:{high:`🔴`,medium:`🟠`,low:`🟢`}},er=new Qn(`priority`,[Jn,Yn,Xn],{[Jn]:G.red,[Yn]:G.yellow,[Xn]:C.muted});function tr(e,t){let n=$n.cli.filled,r=$n.cli.empty,i=``;for(let a=0;a<3;a++)i+=a<e?t(n):C.text(r);return i}function nr(e,t){return 3-t.indexOf(e)}function rr(e,t){if(Zn.has(e))return Zn.get(e);let n=t();return Zn.set(e,n),n}function ir(){return rr(`mcp-priority-all`,()=>({[Jn]:$n.mcp.high,[Yn]:$n.mcp.medium,[Xn]:$n.mcp.low}))}function ar(){return rr(`cli-priority-all`,()=>{let e={};return er.levels.forEach(t=>{let n=nr(t,er.levels),r=er.getColor(t);e[t]=tr(n,r)}),e})}function or(){return rr(`statusbar-priority-all`,()=>{let e={};return er.levels.forEach((t,n)=>{let r=n===0?$n.statusBar.high:n===1?$n.statusBar.medium:$n.statusBar.low,i=er.getColor(t);e[t]=i(r)}),e})}function sr(){return{[Jn]:er.colors[Jn],[Yn]:er.colors[Yn],[Xn]:er.colors[Xn]}}function cr(e=!1){return e?ir():ar()}function lr(e,t=!1){let n=cr(t);return n[e]||n[Yn]}new Qn(`complexity`,[`high`,`medium`,`low`],{high:G.red,medium:G.yellow,low:G.green},{high:e=>e>=7,medium:e=>e>=4&&e<=6,low:e=>e<=3});const ur={clearOnComplete:!1,stopOnComplete:!0,hideCursor:!0,barsize:40},dr={shades_classic:Ae.Presets.shades_classic,shades_grey:Ae.Presets.shades_grey,rect:Ae.Presets.rect,legacy:Ae.Presets.legacy},fr=new class{constructor(e={},t=dr.shades_classic){this.defaultOptions={...ur,...e},this.defaultPreset=t}createSingleBar(e={},t=null){let n=this._mergeConfig(e),r=t||this.defaultPreset;return new Ae.SingleBar(n,r)}createMultiBar(e={},t=null){let n=this._mergeConfig(e),r=t||this.defaultPreset;return new Ae.MultiBar(n,r)}_mergeConfig(e){return{...this.defaultOptions,...e}}setDefaultOptions(e){this.defaultOptions={...this.defaultOptions,...e}}setDefaultPreset(e){this.defaultPreset=e}};function pr(e={}){return fr.createMultiBar(e)}var mr=class{constructor(e={}){this.numUnits=e.numUnits||1,this.unitName=e.unitName||`unit`,this.startTime=null,this.completedUnits=0,this.tokensIn=0,this.tokensOut=0,this.isEstimate=!0,this.bestAvgTimePerUnit=null,this.lastEstimateTime=null,this.lastEstimateSeconds=0,this.multibar=null,this.timeTokensBar=null,this.progressBar=null,this._timerInterval=null,this.isStarted=!1,this.isFinished=!1,this._initializeCustomProperties(e)}_initializeCustomProperties(e){}get unitNamePlural(){return`${this.unitName}s`}start(){this.isStarted||this.isFinished||(this.isStarted=!0,this.startTime=Date.now(),this.multibar=pr(),this.timeTokensBar=this.multibar.create(1,0,{},{format:this._getTimeTokensBarFormat(),barsize:1,hideCursor:!0,clearOnComplete:!1}),this.progressBar=this.multibar.create(this.numUnits,0,{},{format:this._getProgressBarFormat(),barCompleteChar:`█`,barIncompleteChar:`░`}),this._updateTimeTokensBar(),this.progressBar.update(0,{[this.unitNamePlural]:`0/${this.numUnits}`}),this._timerInterval=setInterval(()=>this._updateTimeTokensBar(),1e3),this._setupCustomUI())}_setupCustomUI(){}_getTimeTokensBarFormat(){return`{clock} {elapsed} | Tokens (I/O): {in}/{out} | Est: {remaining}`}_getProgressBarFormat(){return`${this.unitName.charAt(0).toUpperCase()+this.unitName.slice(1)}s {${this.unitNamePlural}} |{bar}| {percentage}%`}updateTokens(e,t,n=!1){this.tokensIn=e||0,this.tokensOut=t||0,this.isEstimate=n,this._updateTimeTokensBar()}_updateTimeTokensBar(){if(!this.timeTokensBar||this.isFinished)return;let e=this._formatElapsedTime(),t=this._estimateRemainingTime(),n=this.isEstimate?`~ Tokens (I/O)`:`Tokens (I/O)`;this.timeTokensBar.update(1,{clock:`⏱️`,elapsed:e,in:this.tokensIn,out:this.tokensOut,remaining:t,tokensLabel:n,...this._getCustomTimeTokensPayload()})}_getCustomTimeTokensPayload(){return{}}_formatElapsedTime(){if(!this.startTime)return`0m 00s`;let e=Math.floor((Date.now()-this.startTime)/1e3);return`${Math.floor(e/60)}m ${(e%60).toString().padStart(2,`0`)}s`}_estimateRemainingTime(){let e=this._getProgressFraction();if(e>=1)return`~0s`;let t=Date.now(),n=(t-this.startTime)/1e3;if(e===0)return`~calculating...`;let r=n/e;(this.bestAvgTimePerUnit===null||r<this.bestAvgTimePerUnit)&&(this.bestAvgTimePerUnit=r);let i=this.numUnits*(1-e),a=Math.ceil(i*this.bestAvgTimePerUnit);if(this.lastEstimateTime){let e=Math.floor((t-this.lastEstimateTime)/1e3),n=Math.max(0,this.lastEstimateSeconds-e);if(n===0)return`~0s`;a=Math.min(a,n)}return this.lastEstimateTime=t,this.lastEstimateSeconds=a,`~${this._formatDuration(a)}`}_getProgressFraction(){return this.completedUnits/this.numUnits}_formatDuration(e){if(e<60)return`${e}s`;let t=Math.floor(e/60),n=e%60;return t<60?n>0?`${t}m ${n}s`:`${t}m`:`${Math.floor(t/60)}h ${t%60}m`}getElapsedTime(){return this.startTime?Date.now()-this.startTime:0}stop(){this.isFinished||(this.isFinished=!0,this._timerInterval&&=(clearInterval(this._timerInterval),null),this.multibar&&(this._updateTimeTokensBar(),this.multibar.stop()),this.cleanup())}getSummary(){return{completedUnits:this.completedUnits,elapsedTime:this.getElapsedTime()}}cleanup(){if(this._timerInterval&&=(clearInterval(this._timerInterval),null),this.multibar){try{this.multibar.stop()}catch{}this.multibar=null}this.timeTokensBar=null,this.progressBar=null,this.isStarted=!1,this.isFinished=!0,this._performCustomCleanup()}_performCustomCleanup(){}},hr=class{constructor(e){if(!e)throw Error(`Multibar instance is required`);this.multibar=e}createBar(e,t={}){if(typeof e!=`string`)throw Error(`Format must be a string`);let n=this.multibar.create(1,1,{},{format:e,barsize:1,hideCursor:!0,clearOnComplete:!1});return n.update(1,t),n}createHeader(e,t){this.createBar(t),this.createBar(e),this.createBar(t)}createRow(e,t){if(!t||typeof t!=`object`)throw Error(`Payload must be an object`);return this.createBar(e,t)}createBorder(e){return this.createBar(e)}};function gr(e,t,n){new hr(e).createHeader(t,n)}function _r(e,t,n){new hr(e).createRow(t,n)}function vr(e,t){new hr(e).createBorder(t)}ar();const yr=or();sr();const br={DEBOUNCE_DELAY:100,MAX_TITLE_LENGTH:57,TRUNCATED_LENGTH:54,TASK_ID_PAD_START:3,TASK_ID_PAD_END:4,PRIORITY_PAD_END:3,VALID_PRIORITIES:[`high`,`medium`,`low`],DEFAULT_PRIORITY:`medium`};var xr=class{constructor(e=br.DEBOUNCE_DELAY){this.delay=e,this.pendingTimeout=null}debounce(e){this.clear(),this.pendingTimeout=setTimeout(()=>{e(),this.pendingTimeout=null},this.delay)}clear(){this.pendingTimeout&&=(clearTimeout(this.pendingTimeout),null)}hasPending(){return this.pendingTimeout!==null}},Sr=class{constructor(){this.priorities={high:0,medium:0,low:0}}increment(e){let t=this.normalize(e);return this.priorities[t]++,t}normalize(e){let t=e?e.toLowerCase():br.DEFAULT_PRIORITY;return br.VALID_PRIORITIES.includes(t)?t:br.DEFAULT_PRIORITY}getCounts(){return{...this.priorities}}},Cr=class{static formatTitle(e,t){return e?e.length>br.MAX_TITLE_LENGTH?e.substring(0,br.TRUNCATED_LENGTH)+`...`:e:`Task ${t}`}static formatPriority(e){return lr(e,!1).padEnd(br.PRIORITY_PAD_END,` `)}static formatTaskId(e){return e.toString().padStart(br.TASK_ID_PAD_START,` `).padEnd(br.TASK_ID_PAD_END,` `)}},wr=class extends mr{_initializeCustomProperties(e){this.append=e.append,this.priorityManager=new Sr,this.debouncer=new xr,this.headerShown=!1}_getTimeTokensBarFormat(){return`{clock} {elapsed} | ${yr.high} {high} ${yr.medium} {medium} ${yr.low} {low} | Tokens (I/O): {in}/{out} | Est: {remaining}`}_getProgressBarFormat(){return`Tasks {tasks} |{bar}| {percentage}%`}_getCustomTimeTokensPayload(){return this.priorityManager.getCounts()}addTaskLine(e,t,n=`medium`){if(!this.multibar||this.isFinished)return;this._ensureHeaderShown();let r=this._updateTaskCounters(e,n);this._updateTimeTokensBar(),this.debouncer.debounce(()=>{this._updateProgressDisplay(e,t,r)})}_ensureHeaderShown(){this.headerShown||(this.headerShown=!0,gr(this.multibar,` TASK | PRI | TITLE`,`------+-----+----------------------------------------------------------------`))}_updateTaskCounters(e,t){let n=this.priorityManager.increment(t);return this.completedUnits=e,n}_updateProgressDisplay(e,t,n){this.progressBar.update(this.completedUnits,{tasks:`${this.completedUnits}/${this.numUnits}`});let r=Cr.formatTitle(t,e),i=Cr.formatPriority(n),a=Cr.formatTaskId(e);_r(this.multibar,` ${a} | ${i} | {title}`,{title:r}),vr(this.multibar,`------+-----+----------------------------------------------------------------`),this._updateTimeTokensBar()}finish(){this.debouncer.hasPending()&&(this.debouncer.clear(),this._updateTimeTokensBar()),this.cleanup(),super.finish()}_performCustomCleanup(){this.debouncer.clear()}getSummary(){return{...super.getSummary(),taskPriorities:this.priorityManager.getCounts(),actionVerb:this.append?`appended`:`generated`}}};function Tr(e={}){return new wr(e)}async function Er(e,t,n){let r=Dr(e,t,n);await kr(e,n,r.estimatedInputTokens);let i=await Ar(e,t,e.streamingTimeout),{progressTracker:a,priorityMap:o}=await jr(e,n),s=await Mr(i.mainResult,e,t,n,a,o,r.defaultPriority,r.estimatedInputTokens,r.logger);if(Or(s),s.usage&&e.projectRoot){let{logAiUsage:t}=await import(`./ai-services-unified-COsdujxy.js`),{getUserId:n}=await import(`./config-manager-Cs19NriM.js`),a=n(e.projectRoot);if(a&&i.providerName&&i.modelId)try{let n=await t({userId:a,commandName:`parse-prd`,providerName:i.providerName,modelId:i.modelId,inputTokens:s.usage.promptTokens||0,outputTokens:s.usage.completionTokens||0,outputType:e.isMCP?`mcp`:`cli`});n&&(i.telemetryData=n)}catch(e){r.logger.report(`Failed to log telemetry: ${e.message}`,`debug`)}}return Hr(s,i,r.estimatedInputTokens,a)}function Dr(e,t,n){let{systemPrompt:r,userPrompt:i}=t;return{logger:new un(e.mcpLog,e.reportProgress),estimatedInputTokens:kn(r+i),defaultPriority:w(e.projectRoot)||`medium`}}function Or(e){if(e.parsedTasks.length===0)throw Error(`No tasks were generated from the PRD`)}async function kr(e,t,n){e.reportProgress&&await e.reportProgress({progress:0,total:t,message:`Starting PRD analysis (Input: ${n} tokens)${e.research?` with research`:``}...`})}async function Ar(e,t,n){let{systemPrompt:r,userPrompt:i}=t;return await an.withTimeout(Ce({role:e.research?`research`:`main`,session:e.session,projectRoot:e.projectRoot,schema:cn,systemPrompt:r,prompt:i,commandName:`parse-prd`,outputType:e.isMCP?`mcp`:`cli`}),n,`Streaming operation`)}async function jr(e,t){let n=cr(e.isMCP),r=null;if(e.outputFormat===`text`&&!e.isMCP){r=Tr({numUnits:t,unitName:`task`,append:e.append});let n=e.research?oe():I(),i=A(e.research?`research`:`main`);yn({prdFilePath:e.prdPath,outputPath:e.tasksPath,numTasks:t,append:e.append,research:e.research,force:e.force,existingTasks:[],nextId:1,model:n||`Default`,temperature:i?.temperature||.7}),r.start()}return{progressTracker:r,priorityMap:n}}async function Mr(e,t,n,r,i,a,o,s,c){let{systemPrompt:l,userPrompt:u}=n,d={config:{...t,schema:cn},numTasks:r,progressTracker:i,priorityMap:a,defaultPriority:o,estimatedInputTokens:s,prompt:u,systemPrompt:l};try{let t={lastPartialObject:null,taskCount:0,estimatedOutputTokens:0,usage:null};if(await Nr(e.partialObjectStream,t,d),e.usage)try{t.usage=await e.usage}catch(e){c.report(`Failed to get usage data: ${e.message}`,`debug`)}return Lr(t,d)}catch(e){return c.report(`StreamObject processing failed: ${e.message}. Falling back to generateObject.`,`debug`),await Vr(d,c)}}async function Nr(e,t,n){for await(let r of e)t.lastPartialObject=r,r&&(t.estimatedOutputTokens=kn(JSON.stringify(r))),await Pr(r,t,n)}async function Pr(e,t,n){if(!e?.tasks||!Array.isArray(e.tasks))return;let r=e.tasks.length;r>t.taskCount?(await Fr(e.tasks,t.taskCount,r,t.estimatedOutputTokens,n),t.taskCount=r):n.progressTracker&&t.estimatedOutputTokens>0&&n.progressTracker.updateTokens(n.estimatedInputTokens,t.estimatedOutputTokens,!0)}async function Fr(e,t,n,r,i){for(let a=t;a<n;a++){let t=e[a]||{};t.title?await Rn({task:t,currentCount:a+1,totalTasks:i.numTasks,estimatedTokens:r,progressTracker:i.progressTracker,reportProgress:i.config.reportProgress,priorityMap:i.priorityMap,defaultPriority:i.defaultPriority,estimatedInputTokens:i.estimatedInputTokens}):await Ir(a+1,r,i)}}async function Ir(e,t,n){let{progressTracker:r,config:i,numTasks:a,defaultPriority:o,estimatedInputTokens:s}=n;r&&(r.addTaskLine(e,`Generating task ${e}...`,o),r.updateTokens(s,t,!0)),i.reportProgress&&!r&&await i.reportProgress({progress:e,total:a,message:`Generating task ${e}/${a}...`})}async function Lr(e,t){let{lastPartialObject:n,estimatedOutputTokens:r,taskCount:i,usage:a}=e;if(!n?.tasks||!Array.isArray(n.tasks))throw Error(`No tasks generated from streamObject`);let o=a?.completionTokens||r,s=a?.promptTokens||t.estimatedInputTokens;return t.progressTracker&&await Rr(n.tasks,i,a?o:r,t,a?s:null),{parsedTasks:n.tasks,estimatedOutputTokens:o,actualInputTokens:s,usage:a,usedFallback:!1}}async function Rr(e,t,n,r,i=null){let{progressTracker:a,defaultPriority:o,estimatedInputTokens:s}=r;t>0?zr(e,a,o):await Br(e,n,r),a.updateTokens(i||s,n,!1),a.stop()}function zr(e,t,n){for(let r=0;r<e.length;r++){let i=e[r];i?.title&&t.addTaskLine(r+1,i.title,i.priority||n)}}async function Br(e,t,n){for(let r=0;r<e.length;r++){let i=e[r];i?.title&&await Rn({task:i,currentCount:r+1,totalTasks:n.numTasks,estimatedTokens:t,progressTracker:n.progressTracker,reportProgress:n.config.reportProgress,priorityMap:n.priorityMap,defaultPriority:n.defaultPriority,estimatedInputTokens:n.estimatedInputTokens})}}async function Vr(e,t){if(t.report(`Using generateObject fallback for PRD parsing`,`info`),e.progressTracker)for(let t=0;t<e.numTasks;t++)e.progressTracker.addTaskLine(t+1,`Generating task ${t+1}...`,e.defaultPriority),e.progressTracker.updateTokens(e.estimatedInputTokens,0,!0);let n=await W({role:e.config.research?`research`:`main`,commandName:`parse-prd`,prompt:e.prompt,systemPrompt:e.systemPrompt,schema:e.config.schema,outputFormat:e.config.outputFormat||`text`,projectRoot:e.config.projectRoot,session:e.config.session}),r=n?.mainResult||n;if(r&&Array.isArray(r.tasks)&&(r.tasks=r.tasks.map(e=>({...e,dependencies:e.dependencies??[],priority:e.priority??null,details:e.details??null,testStrategy:e.testStrategy??null}))),r&&Array.isArray(r.tasks)){if(e.progressTracker){for(let t=0;t<r.tasks.length;t++){let n=r.tasks[t];n&&n.title&&e.progressTracker.addTaskLine(t+1,n.title,n.priority||e.defaultPriority)}let t=n.telemetryData?.outputTokens||kn(JSON.stringify(r)),i=n.telemetryData?.inputTokens||e.estimatedInputTokens;e.progressTracker.updateTokens(i,t,!1)}return{parsedTasks:r.tasks,estimatedOutputTokens:n.telemetryData?.outputTokens||kn(JSON.stringify(r)),actualInputTokens:n.telemetryData?.inputTokens,telemetryData:n.telemetryData,usedFallback:!0}}throw Error(`Failed to generate tasks using generateObject fallback`)}function Hr(e,t,n,r){let i=null;if(r&&(i=r.getSummary(),r.cleanup()),e.usage&&t){let n=e.usage;t.usage||={promptTokens:n.promptTokens||0,completionTokens:n.completionTokens||0,totalTokens:n.totalTokens||0}}return{parsedTasks:e.parsedTasks,aiServiceResponse:t,estimatedInputTokens:e.actualInputTokens||n,estimatedOutputTokens:e.estimatedOutputTokens,usedFallback:e.usedFallback,progressTracker:r,summary:i}}async function Ur(e,t,n){let r=new un(e.mcpLog,e.reportProgress);r.report(`Parsing PRD file: ${e.prdPath}, Force: ${e.force}, Append: ${e.append}, Research: ${e.research}`,`debug`);try{let i=jn(e.tasksPath,e.targetTag),a=e.append?i.existingTasks:[],o=e.append?i.nextId:1;Nn({existingTasks:i.existingTasks,targetTag:e.targetTag,append:e.append,force:e.force,isMCP:e.isMCP,logger:r});let s=await t(e,await Ln(e,An(e.prdPath),o),e.numTasks,o),c=w(e.projectRoot)||`medium`,l=Pn(s.parsedTasks,o,a,c),u=e.append?[...a,...l]:l;return In(e.tasksPath,u,e.targetTag,r),await Wr(e,s,l,u,o,n),{success:!0,tasksPath:e.tasksPath,telemetryData:s.aiServiceResponse?.telemetryData,tagInfo:s.aiServiceResponse?.tagInfo}}catch(t){throw e.isMCP?r.report(`Error parsing PRD: ${t.message}`,`error`):F(e.projectRoot)&&console.error(t),t}}async function Wr(e,t,n,r,i,a){let{aiServiceResponse:o,estimatedInputTokens:s,estimatedOutputTokens:c}=t;if(e.reportProgress){let t=o?.telemetryData&&(o.telemetryData.inputTokens>0||o.telemetryData.outputTokens>0),n;if(t){let e=o.telemetryData.totalCost||0,t=o.telemetryData.currency||`USD`;n=`✅ Task Generation Completed | Tokens (I/O): ${o.telemetryData.inputTokens}/${o.telemetryData.outputTokens} | Cost: ${t===`USD`?`$`:t}${e.toFixed(4)}`}else n=`✅ Task Generation Completed | ~Tokens (I/O): ${s}/${a?c:`unknown`} | Cost: ~$0.00`;await e.reportProgress({progress:e.numTasks,total:e.numTasks,message:n})}e.outputFormat===`text`&&!e.isMCP&&(a&&t.summary?await zn({processedTasks:n,nextId:i,summary:t.summary,prdPath:e.prdPath,tasksPath:e.tasksPath,usedFallback:t.usedFallback,aiServiceResponse:o}):a||Bn({processedTasks:n,research:e.research,finalTasks:r,tasksPath:e.tasksPath,aiServiceResponse:o}))}async function Gr(e,t,n,r={}){return Ur(new ln(e,t,n,r),Er,!0)}async function Kr(e,t,n,r={}){return Ur(new ln(e,t,n,r),Vn,!1)}async function qr(e,t,n,r={}){let i=new ln(e,t,n,r);if(i.useStreaming)try{return await Gr(e,t,n,r)}catch(a){if(a instanceof nn||a.code===rn.NOT_ASYNC_ITERABLE||a.code===rn.STREAM_PROCESSING_FAILED||a.code===rn.STREAM_NOT_ITERABLE||an.isTimeoutError(a)){let o=new un(i.mcpLog,i.reportProgress);return i.outputFormat===`text`&&!i.isMCP?console.log(G.yellow(`⚠️ Streaming operation ${a.message.includes(`timed out`)?`timed out`:`failed`}. Falling back to non-streaming mode...`)):o.report(`Streaming failed (${a.message}), falling back to non-streaming mode...`,`warn`),await Kr(e,t,n,r)}throw a}return await Kr(e,t,n,r)}async function Jr(e,t,n=!1,r=!1,i={}){let{projectRoot:a,tag:o}=i;try{d(`debug`,`Removing subtask ${t}...`);let r=M(e,a,o);if(!r||!r.tasks)throw Error(`Invalid or missing tasks file at ${e}`);if(!t.includes(`.`))throw Error(`Invalid subtask ID format: ${t}. Expected format: "parentId.subtaskId"`);let[i,s]=t.split(`.`),l=parseInt(i,10),u=parseInt(s,10),f=r.tasks.find(e=>e.id===l);if(!f)throw Error(`Parent task with ID ${l} not found`);if(!f.subtasks||f.subtasks.length===0)throw Error(`Parent task ${l} has no subtasks`);let p=f.subtasks.findIndex(e=>e.id===u);if(p===-1)throw Error(`Subtask ${t} not found`);let m={...f.subtasks[p]};f.subtasks.splice(p,1),f.subtasks.length===0&&(f.subtasks=void 0);let h=null;if(n){d(`debug`,`Converting subtask ${t} to a standalone task...`);let e=Math.max(...r.tasks.map(e=>e.id))+1,n=je(m,l,void 0);h={id:e,title:m.title,description:m.description||``,details:m.details||``,status:m.status||`pending`,dependencies:n.dependencies,priority:f.priority||`medium`},c(h,n.metadata),h.dependencies.includes(String(l))||h.dependencies.push(String(l)),Ne(r.tasks,`${l}.${u}`,e),r.tasks.push(h),d(`info`,`Created new task ${e} from subtask ${t}`)}else d(`debug`,`Subtask ${t} deleted`);return E(e,r,a,o),h}catch(e){throw d(`debug`,`Error removing subtask: ${e.message}`),e}}function Yr(e,t){if(typeof t==`string`&&t.includes(`.`)){let n=t.split(`.`);if(n.length!==2||!n[0]||!n[1]){let n=parseInt(t,10);return e.some(e=>e.id===n)}let[r,i]=n,a=parseInt(r,10),o=parseInt(i,10),s=e.find(e=>e.id===a);return s&&s.subtasks&&s.subtasks.some(e=>e.id===o)}let n=parseInt(t,10);return e.some(e=>e.id===n)}async function Xr(t,n,r={}){let{projectRoot:i,tag:o}=r,s={success:!0,messages:[],errors:[],removedTasks:[]},l=n.split(`,`).map(e=>e.trim()).filter(Boolean);if(l.length===0)return s.success=!1,s.errors.push(`No valid task IDs provided.`),s;try{let n=M(t,i,o);if(!n)throw Error(`Could not read tasks file at ${t}`);let r=n._rawTaggedData||n;if(!r[o]||!r[o].tasks)throw Error(`Tag '${o}' not found or has no tasks.`);let u=[];if(await vt(t,o,t=>{let n=t.tasks;for(let e of l)if(Yr(n,e))try{if(typeof e==`string`&&e.includes(`.`)){let[t,r]=e.split(`.`).map(e=>parseInt(e,10)),i=n.find(e=>e.id===t);if(!i||!i.subtasks)throw Error(`Parent task ${t} or its subtasks not found for subtask ${e}`);let a=i.subtasks.findIndex(e=>e.id===r);if(a===-1)throw Error(`Subtask ${r} not found in parent task ${t}`);let c={...i.subtasks[a],parentTaskId:t};s.removedTasks.push(c),i.subtasks.splice(a,1),s.messages.push(`Successfully removed subtask ${e} from tag '${o}'`)}else{let t=parseInt(e,10),r=n.findIndex(e=>e.id===t);if(r===-1)throw Error(`Task with ID ${e} not found in tag '${o}'`);let i=n[r];s.removedTasks.push(i),u.push(t),n.splice(r,1),s.messages.push(`Successfully removed task ${e} from tag '${o}'`)}}catch(t){let n=`Error processing ID ${e}: ${t.message}`;s.errors.push(n),s.success=!1,d(`warn`,n)}else{let t=`Task with ID ${e} in tag '${o}' not found or already removed.`;s.errors.push(t),s.success=!1}if(s.removedTasks.length>0){let t=new Set(l.map(e=>typeof e==`string`&&e.includes(`.`)?e:String(parseInt(e,10))));n.forEach(n=>{n.dependencies&&(n.dependencies=n.dependencies.filter(e=>!t.has(String(e))),c(n,a(n))),n.subtasks&&n.subtasks.forEach(r=>{r.dependencies&&(r.dependencies=r.dependencies.filter(r=>!t.has(e(n.id,r))),c(r,a(r,n.id)))})})}}),s.removedTasks.length>0)for(let e of u){let n=Ee.join(Ee.dirname(t),`task_${e.toString().padStart(3,`0`)}.txt`);if(De.existsSync(n))try{De.unlinkSync(n),s.messages.push(`Deleted task file: ${n}`)}catch(e){let t=`Failed to delete task file ${n}: ${e.message}`;s.errors.push(t),s.success=!1,d(`warn`,t)}}else s.errors.length===0&&s.messages.push(`No tasks found matching the provided IDs.`);let f=s.messages.join(`
73
- `),p=s.errors.join(`
74
- `);return{success:s.success,message:f||`No tasks were removed.`,error:p||null,removedTasks:s.removedTasks}}catch(e){return d(`error`,`Error removing tasks: ${e.message}`),{success:!1,message:``,error:`Operation failed: ${e.message}`,removedTasks:[]}}}const Zr=[`light`,`regular`,`heavy`],Qr=[`done`,`in-progress`,`review`,`cancelled`,`deferred`,`blocked`],$r=[`pending`];function ei(e){return Zr.includes(e)}async function ti(e,t,n){let{projectRoot:r,tag:i,session:a}=n;try{let n={tasks:[e],metadata:{analyzedAt:(/* @__PURE__ */ new Date()).toISOString()}},o=_(null,{projectRoot:r,tag:i},null);if(!o)return d(`warn`,`No complexity report found - cannot re-analyze complexity`),null;await St({file:t,output:o,id:e.id.toString(),projectRoot:r,tag:i,_filteredTasksData:n,_originalTaskCount:1},{session:a});let s=ne(o);if(s){let t=te(s,e.id);if(t)return d(`info`,`Re-analyzed task ${e.id} complexity: ${t.complexityScore}/10`),t.complexityScore}return d(`warn`,`Could not find updated complexity analysis for task ${e.id}`),null}catch(e){return d(`error`,`Failed to re-analyze task complexity: ${e.message}`),null}}function ni(e,t){let{projectRoot:n,tag:r}=t;try{let t=_(null,{projectRoot:n,tag:r},null);if(!t)return null;let i=ne(t);if(!i)return null;let a=te(i,e);return a?a.complexityScore:null}catch(e){return d(`debug`,`Could not read current complexity score: ${e.message}`),null}}async function ri(e,t,n,r,a=`regular`,o=null){let{projectRoot:s,tag:l,session:u}=n;if(!e.subtasks||!Array.isArray(e.subtasks)||e.subtasks.length===0)return{updatedTask:e,regenerated:!1,preserved:0,generated:0};let f=e.subtasks.filter(e=>Qr.includes(e.status)),p=e.subtasks.filter(e=>$r.includes(e.status));if(p.length===0)return{updatedTask:e,regenerated:!1,preserved:f.length,generated:0};let m,h=f.length,g=p.length,_=o?Math.max(.5,o/10):1,v=o?` (original complexity: ${o}/10)`:``;if(r===`up`){if(a===`light`){let e=Math.max(5,h+Math.ceil(g*1.1));m=Math.ceil(e*(.8+.4*_))}else if(a===`regular`){let e=Math.max(6,h+Math.ceil(g*1.3));m=Math.ceil(e*(.8+.4*_))}else{let e=Math.max(8,h+Math.ceil(g*1.6));m=Math.ceil(e*(.8+.6*_))}}else{let e=o>=8?.7:o>=6?.85:1;if(a===`light`){let t=Math.max(3,h+Math.ceil(g*.8));m=Math.ceil(t*e)}else if(a===`regular`){let t=Math.max(3,h+Math.ceil(g*.5));m=Math.ceil(t*e)}else{let e=o>=9?.3:o>=7?.5:.7,t=Math.max(2,h+Math.ceil(g*.25));m=Math.max(1,Math.ceil(t*e))}}d(`debug`,`Complexity-aware subtask calculation${v}: ${g} pending -> target ${m} total`),d(`debug`,`Complexity-aware calculation${v}: ${g} pending -> ${m} total subtasks (${a} ${r})`);let y=Math.max(1,m-h);try{let t=`Based on this updated task, generate ${y} NEW subtasks that reflect the ${r===`up`?`increased`:`decreased`} complexity level:
75
-
76
- **Task Title**: ${e.title}
77
- **Task Description**: ${e.description}
78
- **Implementation Details**: ${e.details}
79
- **Test Strategy**: ${e.testStrategy}
80
-
81
- **Complexity Direction**: This task was recently scoped ${r} (${a} strength) to ${r===`up`?`increase`:`decrease`} complexity.
82
- ${o?`**Original Complexity**: ${o}/10 - consider this when determining appropriate scope level.`:``}
83
-
84
- ${h>0?`**Preserved Subtasks**: ${h} existing subtasks with work already done will be kept.`:``}
85
-
86
- Generate subtasks that:
87
- ${r===`up`?a===`heavy`?`- Add comprehensive implementation steps with advanced features
88
- - Include extensive error handling, validation, and edge cases
89
- - Cover multiple integration scenarios and advanced testing
90
- - Provide thorough documentation and optimization approaches`:a===`regular`?`- Add more detailed implementation steps
91
- - Include additional error handling and validation
92
- - Cover more edge cases and advanced features
93
- - Provide more comprehensive testing approaches`:`- Add some additional implementation details
94
- - Include basic error handling considerations
95
- - Cover a few common edge cases
96
- - Enhance testing approaches slightly`:a===`heavy`?`- Focus ONLY on absolutely essential core functionality
97
- - Strip out ALL non-critical features (error handling, advanced testing, etc.)
98
- - Provide only the minimum viable implementation
99
- - Eliminate any complex integrations or advanced scenarios
100
- - Aim for the simplest possible working solution`:a===`regular`?`- Focus on core functionality only
101
- - Simplify implementation steps
102
- - Remove non-essential features
103
- - Streamline to basic requirements`:`- Focus mainly on core functionality
104
- - Slightly simplify implementation steps
105
- - Remove some non-essential features
106
- - Streamline most requirements`}
107
-
108
- Return a JSON object with a "subtasks" array. Each subtask should have:
109
- - id: Sequential NUMBER starting from 1 (e.g., 1, 2, 3 - NOT "1", "2", "3")
110
- - title: Clear, specific title
111
- - description: Detailed description
112
- - dependencies: Array of dependency IDs as STRINGS (use format ["${e.id}.1", "${e.id}.2"] for siblings, or empty array [] for no dependencies)
113
- - details: Implementation guidance
114
- - status: "pending"
115
- - testStrategy: Testing approach
116
-
117
- IMPORTANT:
118
- - The 'id' field must be a NUMBER, not a string!
119
- - Dependencies must be strings, not numbers!
120
-
121
- Ensure the JSON is valid and properly formatted.`,s=K.object({subtasks:K.array(K.object({id:K.int().positive(),title:K.string().min(5),description:K.string().min(10),dependencies:K.array(K.string()),details:K.string().min(20),status:K.string(),testStrategy:K.string()}))}),l=(await W({role:n.research?`research`:`main`,session:n.session,systemPrompt:`You are an expert project manager who creates task breakdowns that match complexity levels.`,prompt:t,schema:s,objectName:`subtask_regeneration`,commandName:n.commandName||`subtask-regen-${r}`,outputType:n.outputType||`cli`,projectRoot:n.projectRoot})).mainResult.subtasks||[];ii(l);let u=l.map(e=>({...e,status:e.status||`pending`,testStrategy:e.testStrategy||``})),d=f.reduce((e,t)=>Math.max(e,t.id||0),0)+1,p=/* @__PURE__ */ new Map,m=u.map(e=>{let t=e.id,n=d++;return p.set(t,n),{...e,id:n}}).map(t=>{let n={...t,dependencies:(t.dependencies||[]).map(t=>{if(typeof t!=`string`||!t.startsWith(`${e.id}.`))return t;let[,n]=t.split(`.`),r=Number.parseInt(n,10),i=p.get(r);return i?`${e.id}.${i}`:t})};return c(n,i(n,void 0,e.id)),n});return e.subtasks=[...f,...m],{updatedTask:e,regenerated:!0,preserved:f.length,generated:m.length}}catch(t){return d(`warn`,`Failed to regenerate subtasks for task ${e.id}: ${t.message}`),{updatedTask:e,regenerated:!1,preserved:f.length,generated:0,error:t.message}}}function ii(e){if(!Array.isArray(e)||e.length===0)return;let t=e.map(e=>e.id);if(t.some(e=>!Number.isInteger(e)||e<1))throw Error(`Generated subtask ids must be positive integers`);let n=new Set(t);if(n.size!==t.length)throw Error(`Generated subtasks must have unique ids`);let r=[...n].sort((e,t)=>e-t);for(let e=0;e<r.length;e+=1)if(r[e]!==e+1)throw Error(`Generated subtask ids must be sequential starting from 1`)}function ai(e,t,n,r){let i=t===`up`,a={light:i?`minor enhancements`:`slight simplifications`,regular:i?`moderate complexity increases`:`moderate simplifications`,heavy:i?`significant complexity additions`:`major simplifications`},o=`You are tasked with adjusting the complexity of a task.
122
-
123
- CURRENT TASK:
124
- Title: ${e.title}
125
- Description: ${e.description}
126
- Details: ${e.details}
127
- Test Strategy: ${e.testStrategy||`Not specified`}
128
-
129
- ADJUSTMENT REQUIREMENTS:
130
- - Direction: ${i?`INCREASE`:`DECREASE`} complexity
131
- - Strength: ${n} (${a[n]})
132
- - Preserve the core purpose and functionality of the task
133
- - Maintain consistency with the existing task structure`;return o+=i?`
134
- - Add more detailed requirements, edge cases, or advanced features
135
- - Include additional implementation considerations
136
- - Enhance error handling and validation requirements
137
- - Expand testing strategies with more comprehensive scenarios`:`
138
- - Focus on core functionality and essential requirements
139
- - Remove or simplify non-essential features
140
- - Streamline implementation details
141
- - Simplify testing to focus on basic functionality`,r&&(o+=`\n\nCUSTOM INSTRUCTIONS:\n${r}`),o+=`
142
-
143
- Return a JSON object with the updated task containing these fields:
144
- - title: Updated task title
145
- - description: Updated task description
146
- - details: Updated implementation details
147
- - testStrategy: Updated test strategy
148
- - priority: Task priority ('low', 'medium', or 'high')
149
-
150
- Ensure the JSON is valid and properly formatted.`,o}async function oi(e,t,n,r,i){let a=ai(e,t,n,r),o=K.object({title:K.string().min(1).describe(`Updated task title reflecting scope adjustment`),description:K.string().min(1).describe(`Updated task description with adjusted scope`),details:K.string().min(1).describe(`Updated implementation details with adjusted complexity`),testStrategy:K.string().min(1).describe(`Updated testing approach for the adjusted scope`),priority:K.enum([`low`,`medium`,`high`]).describe(`Task priority level`)}),s=await W({role:i.research?`research`:`main`,session:i.session,systemPrompt:`You are an expert software project manager who helps adjust task complexity while maintaining clarity and actionability.`,prompt:a,schema:o,objectName:`updated_task`,commandName:i.commandName||`scope-${t}`,outputType:i.outputType||`cli`,projectRoot:i.projectRoot}),c=s.mainResult,l={...c,priority:c.priority||e.priority||`medium`};return{updatedTask:{...e,...l},telemetryData:s.telemetryData}}async function si(e,t,n=`regular`,r=null,i={},a=`text`){if(!ei(n))throw Error(`Invalid strength level: ${n}. Must be one of: ${Zr.join(`, `)}`);let{projectRoot:o=`.`,tag:s=`master`}=i,c=M(e,o,s),l=c?.tasks||[];for(let e of t)if(!Yr(l,e))throw Error(`Task with ID ${e} not found`);let u=[],f=null;for(let p of t){let t=g(l,p).task;if(!t)throw Error(`Task with ID ${p} not found`);a===`text`&&d(`debug`,`Scoping up task ${p}: ${t.title}`);let m=ni(p,i);m&&a===`text`&&d(`debug`,`Original complexity: ${m}/10`);let h=await oi(t,`up`,n,r,i),_=await ri(h.updatedTask,e,i,`up`,n,m);a===`text`&&_.regenerated&&d(`info`,`Regenerated ${_.generated} pending subtasks (preserved ${_.preserved} completed)`);let v=c.tasks.findIndex(e=>e.id===p);if(v!==-1&&(c.tasks[v]=_.updatedTask,u.push(_.updatedTask)),i.session&&m)try{E(e,c,o,s);let t=await ti(_.updatedTask,e,i);if(t&&a===`text`){let e=t-m;d(`info`,`New complexity: ${m}/10 ${e>0?`↗️`:e<0?`↘️`:`➡️`} ${t}/10 (${e>0?`+`:``}${e})`)}}catch(e){a===`text`&&d(`warn`,`Could not re-analyze complexity: ${e.message}`)}h.telemetryData&&(f?(f.inputTokens+=h.telemetryData.inputTokens||0,f.outputTokens+=h.telemetryData.outputTokens||0,f.totalTokens+=h.telemetryData.totalTokens||0,f.totalCost+=h.telemetryData.totalCost||0):f={...h.telemetryData})}return E(e,c,o,s),a===`text`&&d(`debug`,`Successfully scoped up ${u.length} task(s)`),{updatedTasks:u,telemetryData:f}}async function ci(e,t,n=`regular`,r=null,i={},a=`text`){if(!ei(n))throw Error(`Invalid strength level: ${n}. Must be one of: ${Zr.join(`, `)}`);let{projectRoot:o=`.`,tag:s=`master`}=i,c=M(e,o,s),l=c?.tasks||[];for(let e of t)if(!Yr(l,e))throw Error(`Task with ID ${e} not found`);let u=[],f=null;for(let p of t){let t=g(l,p).task;if(!t)throw Error(`Task with ID ${p} not found`);a===`text`&&d(`debug`,`Scoping down task ${p}: ${t.title}`);let m=ni(p,i);m&&a===`text`&&d(`debug`,`Original complexity: ${m}/10`);let h=await oi(t,`down`,n,r,i),_=await ri(h.updatedTask,e,i,`down`,n,m);a===`text`&&_.regenerated&&d(`info`,`Regenerated ${_.generated} pending subtasks (preserved ${_.preserved} completed)`);let v=c.tasks.findIndex(e=>e.id===p);if(v!==-1&&(c.tasks[v]=_.updatedTask,u.push(_.updatedTask)),i.session&&m)try{E(e,c,o,s);let t=await ti(_.updatedTask,e,i);if(t&&a===`text`){let e=t-m;d(`info`,`New complexity: ${m}/10 ${e>0?`↗️`:e<0?`↘️`:`➡️`} ${t}/10 (${e>0?`+`:``}${e})`)}}catch(e){a===`text`&&d(`warn`,`Could not re-analyze complexity: ${e.message}`)}h.telemetryData&&(f?(f.inputTokens+=h.telemetryData.inputTokens||0,f.outputTokens+=h.telemetryData.outputTokens||0,f.totalTokens+=h.telemetryData.totalTokens||0,f.totalCost+=h.telemetryData.totalCost||0):f={...h.telemetryData})}return E(e,c,o,s),a===`text`&&d(`debug`,`Successfully scoped down ${u.length} task(s)`),{updatedTasks:u,telemetryData:f}}async function li(e,t,r,i=!1,a={},o=a.mcpLog?`json`:`text`){let{session:s,mcpLog:c,projectRoot:l,tag:u}=a,f=n(a.metadata),g=c||d,_=!!c,y=(e,...t)=>{_?typeof g[e]==`function`?g[e](...t):g.info(...t):v()||g(e,...t)},b=null;try{if(y(`debug`,`Updating subtask ${t} with prompt: "${r}"`),!t||typeof t!=`string`)throw Error(`Subtask ID cannot be empty.`);if((!r||typeof r!=`string`||r.trim()===``)&&!f)throw Error(`Prompt cannot be empty unless metadata is provided. Please provide context for the subtask update or metadata to merge.`);let n=l||m();if(!n)throw Error(`Could not determine project root directory`);if(!t.includes(`.`))throw Error(`Invalid subtask ID format: ${t}. In solo mode, subtask ID must be in format "parentId.subtaskId" (e.g., "5.2").`);if(!q.existsSync(e))throw Error(`Tasks file not found at path: ${e}`);let a=M(e,n,u);if(!a||!a.tasks)throw Error(`No valid tasks found in ${e}. The file may be corrupted or have an invalid format.`);let[c,d]=t.split(`.`),g=parseInt(c,10),v=parseInt(d,10);if(Number.isNaN(g)||g<=0||Number.isNaN(v)||v<=0)throw Error(`Invalid subtask ID format: ${t}. Both parent ID and subtask ID must be positive integers.`);let x=a.tasks.find(e=>e.id===g);if(!x)throw Error(`Task ${g} not found`);if(!x.subtasks||!Array.isArray(x.subtasks))throw Error(`Parent task ${g} has no subtasks.`);let S=x.subtasks.findIndex(e=>e.id===v);if(S===-1)throw Error(`Subtask ${t} not found`);let w=x.subtasks[S];if(f&&(!r||r.trim()===``))return y(`debug`,`Metadata-only update for subtask ${t}`),w.metadata={...w.metadata||{},...f},x.subtasks[S]=w,E(e,a,n,u),y(`success`,`Successfully updated metadata for subtask ${t}`),{updatedSubtask:w,telemetryData:null,tagInfo:{tag:u}};let T=``;try{let e=new ge(n,u),i=h(a.tasks),o=new ve(i,`update-subtask`),s=`${x.title} ${w.title} ${r}`,c=o.findRelevantTasks(s,{maxResults:5,includeSelf:!0}),l=o.getTaskIds(c),d=[.../* @__PURE__ */ new Set([t.toString(),...l])];d.length>0&&(T=(await e.gather({tasks:d,format:`research`})).context||``)}catch(e){y(`warn`,`Could not gather context: ${e.message}`)}o===`text`&&(b=U(`Updating subtask ${t}: ${P(w.title,50)}${i?` (with research)`:``}`));let D=``,O=``,k=null;try{let e={id:x.id,title:x.title},t=S>0?{id:`${x.id}.${x.subtasks[S-1].id}`,title:x.subtasks[S-1].title,status:x.subtasks[S-1].status}:void 0,a=S<x.subtasks.length-1?{id:`${x.id}.${x.subtasks[S+1].id}`,title:x.subtasks[S+1].title,status:x.subtasks[S+1].status}:void 0,c=pe(),l={parentTask:e,prevSubtask:t,nextSubtask:a,currentDetails:w.details||`(No existing details)`,updatePrompt:r,useResearch:i,gatheredContext:T||``,hasCodebaseAnalysis:p(i,n,s),projectRoot:n},u=i?`research`:`default`,{systemPrompt:d,userPrompt:f}=await c.loadPrompt(`update-subtask`,l,u),m=i?`research`:`main`;y(`debug`,`Using AI text service with role: ${m}`),k=await we({prompt:f,systemPrompt:d,role:m,session:s,projectRoot:n,maxRetries:2,commandName:`update-subtask`,outputType:_?`mcp`:`cli`}),k&&k.mainResult&&typeof k.mainResult==`string`?D=k.mainResult:(D=``,y(`warn`,`AI service response did not contain expected text string.`)),o===`text`&&b&&(B(b),b=null)}catch(e){throw o===`text`&&b&&(B(b),b=null),e}if(D&&D.trim()){let e=(/* @__PURE__ */ new Date()).toISOString(),t=`<info added on ${e}>\n${D.trim()}\n</info added on ${e}>`;O=t,w.details=(w.details?w.details+`
151
- `:``)+t}else y(`warn`,`AI response was empty or whitespace after trimming. Original details remain unchanged.`),O=`No new details were added by the AI.`;let A=x.subtasks[S];return f&&(A.metadata={...A.metadata||{},...f}),o===`text`&&F(s)&&console.log(`>>> DEBUG: Subtask details AFTER AI update:`,A.details),A.description&&r.length<100&&(o===`text`&&F(s)&&console.log(`>>> DEBUG: Subtask description BEFORE append:`,A.description),A.description+=` [Updated: ${(/* @__PURE__ */ new Date()).toLocaleDateString()}]`,o===`text`&&F(s)&&console.log(`>>> DEBUG: Subtask description AFTER append:`,A.description)),o===`text`&&F(s)&&console.log(`>>> DEBUG: About to call writeJSON with updated data...`),E(e,a,n,u),o===`text`&&F(s)&&console.log(`>>> DEBUG: writeJSON call completed.`),y(`debug`,`Successfully updated subtask ${t}`),o===`text`&&(b&&=(B(b),null),console.log(J(G.green(`Successfully updated subtask #${t}`)+`
152
-
153
- `+C.text.bold(`Title:`)+` `+A.title+`
154
-
155
- `+C.text.bold(`Newly Added Snippet:`)+`
156
- `+C.text(O),{padding:1,borderColor:`green`,borderStyle:`round`}))),o===`text`&&k.telemetryData&&H(k.telemetryData,`cli`),{updatedSubtask:A,telemetryData:k.telemetryData,tagInfo:k.tagInfo}}catch(e){throw o===`text`&&b&&(B(b),b=null),o!==`text`&&y(`error`,`Error updating subtask: ${e.message}`),e}}async function ui(e,t,r,a=!1,o={},s=`text`,l=!1){let{session:u,mcpLog:d,projectRoot:f,tag:g}=o,_=n(o.metadata),{report:v,isMCP:y}=Et(d,u);try{if(v(`debug`,`Updating single task ${t} with prompt: "${r}"`),t==null||String(t).trim()===``)throw Error(`Task ID cannot be empty.`);if((!r||typeof r!=`string`||r.trim()===``)&&!_)throw Error(`Prompt cannot be empty unless metadata is provided for update.`);let n=f||m();if(!n)throw Error(`Could not determine project root directory`);if(!q.existsSync(e))throw Error(`Tasks file not found: ${e}`);let o=M(e,n,g);if(!o||!o.tasks)throw Error(`No valid tasks found in ${e}.`);let d=String(t).trim();if(!/^\d+$/.test(d))throw Error(`taskId must be a positive integer. Use update-subtask-by-id for IDs like "1.2".`);let b=Number(d),x=o.tasks.findIndex(e=>e.id===b);if(x===-1)throw Error(`Task ${b} not found`);let S=o.tasks[x];if(S.status===`done`||S.status===`completed`)return v(`warn`,`Task ${t} is already marked as done and cannot be updated`),s===`text`&&console.log(J(G.yellow(`Task ${t} is already marked as ${S.status} and cannot be updated.`)+`
157
-
158
- `+C.text(`Completed tasks are locked to maintain consistency. To modify a completed task, you must first:`)+`
159
- `+C.text(`1. Change its status to "pending" or "in-progress"`)+`
160
- `+C.text(`2. Then run the update-task command`),{padding:1,borderColor:`yellow`,borderStyle:`round`})),null;if(_&&(!r||r.trim()===``))return v(`debug`,`Metadata-only update for task ${t}`),S.metadata={...S.metadata||{},..._},o.tasks[x]=S,E(e,o,n,g),v(`success`,`Successfully updated metadata for task ${t}`),{updatedTask:S,telemetryData:null,tagInfo:{tag:g}};let w=``;try{let e=new ge(n,g),i=h(o.tasks),a=new ve(i,`update-task`),s=`${S.title} ${S.description} ${r}`,c=a.findRelevantTasks(s,{maxResults:5,includeSelf:!0}),l=a.getTaskIds(c),u=[.../* @__PURE__ */ new Set([t.toString(),...l])];u.length>0&&(w=(await e.gather({tasks:u,format:`research`})).context||``)}catch(e){v(`warn`,`Could not gather context: ${e.message}`)}let T=pe(),D={task:S,taskJson:JSON.stringify(S,null,2),updatePrompt:r,appendMode:l,useResearch:a,currentDetails:S.details||`(No existing details)`,gatheredContext:w||``,hasCodebaseAnalysis:p(a,n,u),projectRoot:n},O=l?`append`:a?`research`:`default`;v(`debug`,`Loading prompt template with variant: ${O}, appendMode: ${l}, useResearch: ${a}`);let k,A;try{let e=T.loadPrompt(`update-task`,D,O);v(`debug`,`Prompt result type: ${typeof e}, keys: ${e?Object.keys(e).join(`, `):`null`}`),k=e.systemPrompt,A=e.userPrompt,v(`debug`,`Loaded prompts - systemPrompt length: ${k?.length}, userPrompt length: ${A?.length}`)}catch(e){throw v(`error`,`Failed to load prompt template: ${e.message}`),Error(`Failed to load prompt template: ${e.message}`)}if(!k||!A)throw Error(`Failed to load prompts: systemPrompt=${!!k}, userPrompt=${!!A}`);let j=null,N=null;!y&&s===`text`&&(j=U(`Updating task ${t}: ${P(S.title,50)}${a?` (with research)`:``}`));try{let d=a?`research`:`main`;if(N=l?await we({role:d,session:u,projectRoot:n,systemPrompt:k,prompt:A,commandName:`update-task`,outputType:y?`mcp`:`cli`}):await W({role:d,session:u,projectRoot:n,systemPrompt:k,prompt:A,schema:_t[`update-task-by-id`],objectName:`task`,commandName:`update-task`,outputType:y?`mcp`:`cli`}),j&&B(j,`AI update complete.`),l){let i=N.mainResult,a=``;if(i&&i.trim()){let e=(/* @__PURE__ */ new Date()).toISOString(),t=`<info added on ${e}>\n${i.trim()}\n</info added on ${e}>`;a=t,S.details=(S.details?S.details+`
161
- `:``)+t}else v(`warn`,`AI response was empty or whitespace after trimming. Original details remain unchanged.`),a=`No new details were added by the AI.`;return r.length<100&&S.description&&(S.description+=` [Updated: ${(/* @__PURE__ */ new Date()).toLocaleDateString()}]`),_&&(S.metadata={...S.metadata||{},..._}),o.tasks[x]=S,E(e,o,n,g),v(`debug`,`Successfully appended to task ${t}`),s===`text`&&console.log(J(G.green(`Successfully appended to task #${t}`)+`
162
-
163
- `+C.text.bold(`Title:`)+` `+S.title+`
164
-
165
- `+C.text.bold(`Newly Added Content:`)+`
166
- `+C.text(a),{padding:1,borderColor:`green`,borderStyle:`round`})),s===`text`&&N.telemetryData&&H(N.telemetryData,`cli`),{updatedTask:S,telemetryData:N.telemetryData,tagInfo:N.tagInfo}}let f=N.mainResult?.task;if(!f||typeof f!=`object`)throw Error(`Received invalid task object from AI.`);let p={...f,dependencies:f.dependencies??[],priority:f.priority??null,details:f.details??null,testStrategy:f.testStrategy??null};if(!p.title||!p.description)throw Error(`Updated task missing required fields.`);if(p.id!==t&&(v(`debug`,`AI changed task ID. Restoring original ID ${t}.`),p.id=t),p.status!==S.status&&!r.toLowerCase().includes(`status`)&&(v(`warn`,`AI changed task status. Restoring original status '${S.status}'.`),p.status=S.status),p.subtasks&&Array.isArray(p.subtasks)){let e=1;p.subtasks=p.subtasks.map(t=>{let n=S.subtasks?.find(e=>String(e.id)===String(t.id)||t.title&&e.title===t.title),r={...t,id:e,dependencies:Array.isArray(t.dependencies)?t.dependencies.map(e=>typeof e==`string`?parseInt(e,10):e).filter(t=>!Number.isNaN(t)&&t>=1&&t<e):[],status:t.status||`pending`,testStrategy:t.testStrategy??null,...n?.metadata&&{metadata:n.metadata}};return e++,c(r,i(r,n,S.id)),r}),v(`debug`,`Fixed ${p.subtasks.length} subtask IDs to be sequential numeric IDs.`)}if(S.subtasks?.length>0){if(!p.subtasks)v(`warn`,`Subtasks removed by AI. Restoring original subtasks.`),p.subtasks=S.subtasks;else{S.subtasks.filter(e=>e.status===`done`||e.status===`completed`).forEach(e=>{let t=p.subtasks.find(t=>t.id===e.id);(!t||JSON.stringify(t)!==JSON.stringify(e))&&(v(`warn`,`Completed subtask ${e.id} was modified or removed. Restoring.`),p.subtasks=p.subtasks.filter(t=>t.id!==e.id),p.subtasks.push(e))});let e=/* @__PURE__ */ new Set;p.subtasks=p.subtasks.filter(t=>e.has(t.id)?(v(`warn`,`Duplicate subtask ID ${t.id} removed.`),!1):(e.add(t.id),!0))}}let m=i(p,S);return(m||_)&&(p.metadata={...m||{},..._||{}}),o.tasks[x]=p,E(e,o,n,g),v(`success`,`Updated task ${t}`),s===`text`&&N.telemetryData&&H(N.telemetryData,`cli`),{updatedTask:p,telemetryData:N.telemetryData,tagInfo:N.tagInfo}}catch(e){throw j&&B(j),e}}catch(e){throw s!==`text`&&v(`error`,`Error updating task: ${e.message}`),e}}async function di(e,t,n,r=!1,a={},o=`text`){let{session:s,mcpLog:l,projectRoot:u,tag:f}=a,g=l||d,_=!!l;_?g.debug(`updateTasks called with context: session=${!!s}`):g(`info`,`updateTasks called`);try{_?g.debug(`Updating tasks from ID ${t}`):g(`debug`,`Updating tasks from ID ${t} with prompt: "${n}"`);let a=u||m();if(!a)throw Error(`Could not determine project root directory`);let l=M(e,a,f);if(!l||!l.tasks)throw Error(`No valid tasks found in ${e}`);let d=l.tasks.filter(e=>e.id>=t&&e.status!==`done`);if(d.length===0){_?g.info(`No tasks to update (ID >= ${t} and not 'done').`):g(`info`,`No tasks to update (ID >= ${t} and not 'done').`),o===`text`&&console.log();return}let v=``;try{let e=new ge(a,f),t=h(l.tasks),r=new ve(t,`update`),i=r.findRelevantTasks(n,{maxResults:5,includeSelf:!0}),o=r.getTaskIds(i),s=d.map(e=>e.id.toString()),c=[.../* @__PURE__ */ new Set([...s,...o])];c.length>0&&(v=(await e.gather({tasks:c,format:`research`})).context||``)}catch(e){g(`warn`,`Could not gather additional context: ${e.message}`)}if(o===`text`){let e=new Oe({head:[G.cyan.bold(`ID`),G.cyan.bold(`Title`),G.cyan.bold(`Status`)],colWidths:[5,70,20],style:{border:k}});d.forEach(t=>{e.push([t.id,P(t.title,57),Se(t.status)])}),console.log(J(C.text.bold(`Updating ${d.length} tasks`),{padding:1,borderColor:L,borderStyle:`round`,margin:{top:1,bottom:0}})),console.log(e.toString())}let{systemPrompt:y,userPrompt:b}=await pe().loadPrompt(`update-tasks`,{tasks:d,updatePrompt:n,useResearch:r,projectContext:v,hasCodebaseAnalysis:p(r,a,s),projectRoot:a}),x=null,S=null;!_&&o===`text`&&(x=U(`Updating tasks with AI...
167
- `));try{S=await W({role:r?`research`:`main`,session:s,projectRoot:a,systemPrompt:y,prompt:b,schema:_t[`update-tasks`],objectName:`tasks`,commandName:`update-tasks`,outputType:_?`mcp`:`cli`}),x&&B(x,`AI update complete.`);let t=S.mainResult.tasks.map(e=>({...e,dependencies:e.dependencies??[],priority:e.priority??null,details:e.details??null,testStrategy:e.testStrategy??null,subtasks:e.subtasks?e.subtasks.map(e=>({...e,dependencies:e.dependencies??[],status:e.status??`pending`,testStrategy:e.testStrategy??null})):null}));if(!Array.isArray(t))throw Error(`Parsed AI response for updated tasks was not an array.`);_?g.info(`Received ${t.length} updated tasks from AI.`):g(`debug`,`Received ${t.length} updated tasks from AI.`);let n=new Map(t.map(e=>[e.id,e])),u=new Set(d.map(e=>e.id)),p=0;return l.tasks.forEach((e,t)=>{if(u.has(e.id)&&n.has(e.id)){let r=n.get(e.id),a={...e,...r,subtasks:r.subtasks==null?e.subtasks:r.subtasks};for(let t of[`priority`,`details`,`testStrategy`])r[t]??(a[t]=e[t]);c(a,i(a,e)),Array.isArray(a.subtasks)&&(a.subtasks=a.subtasks.map(t=>{let n=e.subtasks?.find(e=>String(e.id)===String(t.id)),r={...t};return delete r.metadata,r.testStrategy==null&&n&&(r.testStrategy=n.testStrategy),c(r,i(t,n,e.id)),r})),l.tasks[t]=a,p++}}),_?g.info(`Applied updates to ${p} tasks in the dataset.`):g(`debug`,`Applied updates to ${p} tasks in the dataset.`),E(e,l,a,f),_?g.info(`Successfully updated ${p} tasks in ${e}`):g(`success`,`Successfully updated ${p} tasks in ${e}`),o===`text`&&S.telemetryData&&H(S.telemetryData,`cli`),{success:!0,updatedTasks:t,telemetryData:S.telemetryData,tagInfo:S.tagInfo}}catch(e){throw x&&B(x),_?g.error(`Error during AI service call: ${e.message}`):g(`error`,`Error during AI service call: ${e.message}`),e.message.includes(`API key`)&&(_?g.error(`Please ensure API keys are configured correctly in .env or mcp.json.`):g(`error`,`Please ensure API keys are configured correctly in .env or mcp.json.`)),e}finally{x&&B(x)}}catch(e){if(_?g.error(`Error updating tasks: ${e.message}`):g(`error`,`Error updating tasks: ${e.message}`),o===`text`)console.error(G.red(`Error: ${e.message}`)),F(s)&&console.error(e),process.exit(1);else throw e}}export{Ye as C,ze as S,Ke as T,Tt as _,si as a,tt as b,Yr as c,Vt as d,en as f,Dt as g,Ot as h,ci as i,Jr as l,kt as m,ui as n,ei as o,At as p,li as r,Xr as s,di as t,qr as u,St as v,Be as w,Re as x,bt as y};
@@ -1 +0,0 @@
1
- import{_ as e,a as t,b as n,c as r,d as i,g as a,h as o,i as s,l as c,m as l,n as u,o as d,p as f,r as p,s as m,t as h,u as g,v as _,y as v}from"./task-manager-C-lF7v2M.js";import{K as y,rt as b}from"./config-manager-CtE1yo1I.js";import{h as x}from"./src-Dz_uZuYA.js";import{n as S}from"./research-DcB3PdqA.js";import{t as C}from"./response-language-BdYSHT6o.js";export{n as addSubtask,v as addTask,_ as analyzeTaskComplexity,e as clearSubtasks,o as expandAllTasks,a as expandTask,x as findNextTask,y as findTaskById,l as isTaskDependentOn,f as listTasks,i as moveTask,g as parsePRD,S as performResearch,b as readComplexityReport,c as removeSubtask,m as removeTask,s as scopeDownTask,t as scopeUpTask,C as setResponseLanguage,r as taskExists,p as updateSubtaskById,u as updateTaskById,h as updateTasks,d as validateStrength};