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.
@@ -0,0 +1,489 @@
1
+ import{t as e}from"./rolldown-runtime-BxhE39jg.js";import{C as t,G as n,J as r,K as i,S as a,T as o,V as s,X as c,Z as l,a as u,b as d,et as f,g as p,h as m,i as h,m as ee,n as te,o as ne,q as re,r as ie,s as g,t as ae,w as _,x as oe,y as v,z as se}from"./src-BQZsjzA5.js";import{$ as y,B as ce,P as le,T as ue,X as b,Z as de,_t as x,a as fe,d as pe,dt as me,ft as he,gt as ge,ht as _e,it as S,j as ve,m as ye,mt as be,n as xe,p as Se,pt as C,tt as Ce,u as we,v as Te,y as Ee}from"./config-manager-DTkRerDn.js";import w from"chalk";import T,{resolve as De}from"node:path";import E from"node:fs";import{stripVTControlCharacters as Oe}from"node:util";import ke from"path";import{spawn as Ae}from"child_process";import je from"node:os";import D from"fs";import{Argument as Me,Command as O}from"commander";import Ne from"figlet";import Pe from"gradient-string";import Fe from"terminal-link";import k from"boxen";import{Marked as Ie,marked as Le}from"marked";import{markedTerminal as Re}from"marked-terminal";import ze from"turndown";import Be from"cli-table3";import Ve from"ora";import He from"process";import Ue from"inquirer";const We={done:{color:w.green,icon:`✓`,tableIcon:`✓`},pending:{color:w.yellow,icon:`○`,tableIcon:`○`},"in-progress":{color:x.active,icon:`▶`,tableIcon:`▶`},deferred:{color:x.muted,icon:`–`,tableIcon:`–`},review:{color:w.magenta,icon:`?`,tableIcon:`?`},cancelled:{color:x.muted,icon:`x`,tableIcon:`x`},blocked:{color:w.red,icon:`!`,tableIcon:`!`},completed:{color:w.green,icon:`✓`,tableIcon:`✓`}};function Ge(e){let t=We[e];return t?t.color(t.icon):w.red(`X`)}function A(e,t=!1){let n=We[e]||{color:w.red,icon:`X`,tableIcon:`X`},r=t?n.tableIcon:n.icon;return n.color(`${r} ${e}`)}function j(e=.9,t=40){return Math.max(Math.floor(M()*e),t)}function Ke(e=process.stdout,t=process.env){if(e.columns&&e.columns>0)return e.columns;let n=t.COLUMNS?.trim();if(n&&/^\d+$/.test(n)){let e=Number.parseInt(n,10);if(e>0)return Math.min(e,1e3)}}function M(e=process.stdout,t=process.env){return Ke(e,t)??80}function N(e=process.stdout,t=process.env){let n=Ke(e,t);return n?Math.floor(n*.95):100}function qe(e,t,n=20){let r=e=>e.reduce((e,t)=>e+(t.width===`flex`?n:t.width),0)+e.length+1,i=[...t],a=[],o=t.filter(e=>e.dropOrder!==void 0).sort((e,t)=>(e.dropOrder??0)-(t.dropOrder??0));for(let t of o){if(r(i)<=e)break;i=i.filter(e=>e!==t),a.push(t.key)}let s=i.reduce((e,t)=>e+(t.width===`flex`?0:t.width),0),c=Math.max(n,e-s-i.length-1);return{keys:i.map(e=>e.key),widths:i.map(e=>e.width===`flex`?c:e.width),hidden:a}}function P(e,t){return e.length<=t?e:e.substring(0,t-3)+`...`}function Je(e,t,n=30){if(t===0)return x.muted(`No tasks`);let r=Math.round(e/t*100),i=Math.round(e/t*n),a=n-i;return`${w.green(`█`).repeat(i)+x.muted(`░`).repeat(a)} ${w.cyan(`${r}%`)} (${e}/${t})`}function F(e,t,n){let r=e.match(/^ */)?.[0]??``,i=e.slice(r.length).split(` `),a=[],o=r,s=r.length,c=!1;for(let e of i){let r=Oe(e).length;c&&s+1+r>t?(a.push(o),o=n+e,s=n.length+r):(o+=(c?` `:``)+e,s+=+!!c+r),c=!0}return a.push(o),a}const Ye=e=>e.replace(/\x1b\[[0-9;]*m/g,``).length,Xe=e=>x.brand(e),Ze=e=>e.length<2?e.join(``):`${e.slice(0,-1).join(`, `)} and ${e[e.length-1]}`,Qe=(e,t)=>t?`${e} (${t})`:e;function $e(e){return e.status===`done`||e.status===`completed`?[`Already done.`]:e.status===`cancelled`?[`Cancelled.`]:e.status===`pending`?[`Not blocked. Start it with: ${Xe(`taskgraph set-status --id=${e.id} --status=in-progress`)}`]:[`Not blocked by any dependencies (status: ${e.status}).`]}function et(e,t={}){let n=t.width??100,r=[],i=e=>{if(e.repeated)return`shown above`;let t={ready:`ready to start`,stalled:`${e.status}, needs a decision`,missing:`missing`,cycle:`loops back`};return e.kind?t[e.kind]:``},a=(e,t)=>{let r=`${t}${e.kind===`missing`?w.yellow(`⚠`):Ge(e.status)} ${x.brand(e.id)} `,a=i(e)?x.muted(` ← ${i(e)}`):``;return r+P(e.kind===`missing`?`no such task`:e.title??``,Math.max(12,n-Ye(r)-Ye(a)))+a},o=(e,t,n)=>{r.push(a(e,t+x.muted(n?`└─ `:`├─ `)));let i=t+x.muted(n?` `:`│ `);e.blockers.forEach((t,n)=>o(t,i,n===e.blockers.length-1))};if(r.push(`${Ge(e.status)} ${x.brand(e.id)} ${P(e.title,Math.max(12,n-e.id.length-4))}`),!e.blocked)return r.push(...$e(e)),r;r.push(`Blocked by:`),e.blockers.forEach((t,n)=>o(t,``,n===e.blockers.length-1));let s=tt(e.rootCauses);return s.length&&r.push(``,`To unblock:`,...s.map(e=>` ${e}`)),r}function tt(e){let t=[],n=e.filter(e=>e.kind===`ready`);n.length&&t.push(`Do ${Ze(n.map(e=>Qe(e.id,e.title)))}: nothing else stands in ${n.length>1?`their`:`its`} way.`);for(let n of e)if(n.kind===`stalled`)t.push(`${n.id} is ${n.status}. Reopen it with: ${Xe(`taskgraph set-status --id=${n.id} --status=pending`)}`);else if(n.kind===`missing`){let e=(n.listedBy??[]).map(e=>Xe(`taskgraph remove-dependency --id=${e} --depends-on=${n.id}`));t.push(`${n.id} is not a task. Remove it with: ${Ze(e)}`)}else if(n.kind===`cycle`){let e=(n.edges??[]).map(e=>Xe(`taskgraph remove-dependency --id=${e.from} --depends-on=${e.to}`)),r=n.cycle??[n.id];t.push(r.length===1?`${n.id} depends on itself. Remove it with: ${Ze(e)}`:`${r.join(`, `)} depend on each other. Break the loop with: ${Ze(e)}`)}return t}function I(e,t,n){return(n?.color?w[n.color]:w.cyan)(Fe(e,t,{fallback:(e,t)=>n?.textOnlyFallback?e:`${e} (${t})`}))}function nt(e,t){return I(e,e,t)}function rt(e,t){return I(e,t,{color:`cyan`})}function it(){return Fe.isSupported}const at=Pe(he);function ot(){return process.env.TM_HIDE_BANNER===`true`}const st=/* @__PURE__ */ new Set([`--help`,`-h`,`help`]);function ct(e,t){return!t||e.includes(`--no-banner`)?!1:e.length===0||e.length===1&&st.has(e[0])}function lt(e={}){if(ot())return;let{version:t}=e;try{let e=Ne.textSync(`TaskGraph`,{font:`Standard`,horizontalLayout:`default`,verticalLayout:`default`});console.log(at(e))}catch{console.log(at(`=== TaskGraph ===`))}let n=`x.com/stephennmiller_`,r=I(n,`https://x.com/stephennmiller_`,{textOnlyFallback:!0}),i=w.dim(`by `)+w.cyan(r),a=t?t.replace(/^v/,``):``,o=`https://github.com/stephennmiller/taskgraph-ai/releases/tag/taskgraph-ai%40${a}`,s=t?I(`v${a}`,o,{color:`dim`,textOnlyFallback:!0}):``;if(s){let e=`by ${n}`.length,t=a.length+1,r=M()-e-t-1;r>=2?console.log(i+` `.repeat(r)+s):(console.log(i),console.log(s))}else console.log(i);console.log(``)}function ut(){if(ot())return;try{let e=Ne.textSync(`TaskGraph`,{font:`Standard`,horizontalLayout:`default`,verticalLayout:`default`});console.log(at(e))}catch{console.log(at(`=== TaskGraph ===`))}let e=I(`x.com/stephennmiller_`,`https://x.com/stephennmiller_`,{textOnlyFallback:!0});console.log(w.dim(`by `)+w.cyan(e)),console.log(``)}function dt(e){let{header:t,body:n,callToAction:r,footer:i,level:a=`warn`}=e,o=a===`info`?x.heading:w.yellow.bold,s=a===`info`?C:`yellow`,c=[o(t),...n.map(e=>x.text(e))];r&&r.label&&r.action&&c.push(w.cyan(r.label)+`
2
+ `+x.brand.underline(r.action)),i&&c.push(x.muted(i));let l=c.join(`
3
+
4
+ `);return k(l,{padding:1,borderColor:s,borderStyle:`round`,margin:{top:1,bottom:1}})}const L={done:w.green(`█`),cancelled:x.muted(`─`),deferred:x.muted(`─`),inProgress:x.active(`▓`),review:w.magenta(`▒`),pending:w.yellow(`░`),blocked:w.red(`!`)};function ft(e,t=30,n){if(!n){let n=Math.round(e/100*t),r=t-n;return L.done.repeat(n)+x.muted(`░`).repeat(r)}let r=``,i=0,a=[[n.done,L.done],[n.cancelled,L.cancelled],[n.deferred,L.deferred],[n[`in-progress`],L.inProgress],[n.review,L.review],[n.pending,L.pending],[n.blocked,L.blocked]];for(let[e,n]of a){if(!e||i>=t)continue;let a=Math.min(Math.round(e/100*t),t-i);a>0&&(r+=n.repeat(a),i+=a)}return i<t&&(r+=L.pending.repeat(t-i)),r}function pt(e){let t={total:e.length,done:0,inProgress:0,pending:0,blocked:0,deferred:0,cancelled:0,review:0,completionPercentage:0,completedCount:0};return e.forEach(e=>{switch(e.status){case`done`:t.done++;break;case`in-progress`:t.inProgress++;break;case`pending`:t.pending++;break;case`blocked`:t.blocked++;break;case`deferred`:t.deferred++;break;case`cancelled`:t.cancelled++;break;case`review`:t.review=(t.review||0)+1}}),t.completedCount=e.filter(e=>_(e.status)).length,t.completionPercentage=t.total>0?Math.round(t.completedCount/t.total*100):0,t}function mt(e){let t={total:0,done:0,inProgress:0,pending:0,blocked:0,deferred:0,cancelled:0,review:0,completionPercentage:0,completedCount:0},n=[];return e.forEach(e=>{e.subtasks&&e.subtasks.length>0&&e.subtasks.forEach(e=>{switch(t.total++,n.push(e),e.status){case`done`:t.done++;break;case`in-progress`:t.inProgress++;break;case`pending`:t.pending++;break;case`blocked`:t.blocked++;break;case`deferred`:t.deferred++;break;case`cancelled`:t.cancelled++;break;case`review`:t.review=(t.review||0)+1}})}),t.completedCount=n.filter(e=>_(e.status)).length,t.completionPercentage=t.total>0?Math.round(t.completedCount/t.total*100):0,t}function ht(e){let t=new Set(e.filter(e=>_(e.status)).map(e=>e.id)),n=e.filter(e=>!_(e.status)&&(!e.dependencies||e.dependencies.length===0)).length,r=e.filter(e=>!_(e.status)&&e.dependencies&&e.dependencies.length>0&&e.dependencies.every(e=>t.has(e))).length,i=e.filter(e=>!_(e.status)&&e.dependencies&&e.dependencies.length>0&&!e.dependencies.every(e=>t.has(e))).length,a={};e.forEach(e=>{e.dependencies&&e.dependencies.length>0&&e.dependencies.forEach(e=>{let t=String(e);a[t]=(a[t]||0)+1})});let o,s=0;for(let[e,t]of Object.entries(a))t>s&&(s=t,o=parseInt(e));let c=e.reduce((e,t)=>e+(t.dependencies?t.dependencies.length:0),0),l=e.length>0?c/e.length:0;return{tasksWithNoDeps:n,tasksReadyToWork:n+r,tasksBlockedByDeps:i,mostDependedOnTaskId:o,mostDependedOnCount:s,avgDependenciesPerTask:l}}function gt(e){let t={critical:0,high:0,medium:0,low:0};return e.forEach(e=>{let n=e.priority||`medium`;t[n]++}),t}function _t(e){return e.total===0?{}:{done:e.done/e.total*100,"in-progress":e.inProgress/e.total*100,pending:e.pending/e.total*100,blocked:e.blocked/e.total*100,deferred:e.deferred/e.total*100,cancelled:e.cancelled/e.total*100,review:(e.review||0)/e.total*100}}function vt(e,t=!1,n=!1){let r=[];t?r.push(`${L.done} Completed: ${w.green(`${e.completedCount}/${e.total}`)}`):r.push(`${L.done} Done: ${w.green(e.done)}`),r.push(`${L.cancelled} Cancelled: ${x.muted(e.cancelled)}`),r.push(`${L.deferred} Deferred: ${x.muted(e.deferred)}`);let i=e=>n?e.slice(0,2).join(` `)+(e.length>2?`
5
+ `+e.slice(2).join(` `):``):e.join(` `),a=i(r);return r.length=0,r.push(`${L.inProgress} In Progress: ${x.active(e.inProgress)}`),r.push(`${L.review} Review: ${w.magenta(e.review||0)}`),r.push(`${L.pending} Pending: ${w.yellow(e.pending)}`),r.push(`${L.blocked} Blocked: ${w.red(e.blocked)}`),a+`
6
+ `+i(r)}function yt(e,t,n,r=!1){let i=_t(e),a=_t(t),o=r?16:30,s=ft(e.completionPercentage,o,i),c=ft(t.completionPercentage,o,a),l=`${e.completionPercentage}% ${e.completedCount}/${e.total}`,u=`${t.completionPercentage}% ${t.completedCount}/${t.total}`;return w.bold(`Project Dashboard`)+`
7
+ Tasks Progress: ${s} ${w.yellow(l)}\n`+vt(e,!1,r)+`
8
+
9
+ Subtasks Progress: ${c} ${w.cyan(u)}\n`+vt(t,!0,r)+`
10
+
11
+ `+w.cyan.bold(`Priority Breakdown:`)+`
12
+ ${w.red(`•`)} ${x.text(`High priority:`)} ${n.high}\n${w.yellow(`•`)} ${x.text(`Medium priority:`)} ${n.medium}\n${w.green(`•`)} ${x.text(`Low priority:`)} ${n.low}`}function bt(e,t){return w.bold(`Dependency Status & Next Task`)+`
13
+ `+w.cyan.bold(`Dependency Metrics:`)+`
14
+ ${w.green(`•`)} ${x.text(`Tasks with no dependencies:`)} ${e.tasksWithNoDeps}\n${w.green(`•`)} ${x.text(`Tasks ready to work on:`)} ${e.tasksReadyToWork}\n${w.yellow(`•`)} ${x.text(`Tasks blocked by dependencies:`)} ${e.tasksBlockedByDeps}\n${x.accent(`•`)} ${x.text(`Most depended-on task:`)} ${e.mostDependedOnTaskId?w.cyan(`#${e.mostDependedOnTaskId} (${e.mostDependedOnCount} dependents)`):x.muted(`None`)}\n${x.brand(`•`)} ${x.text(`Avg dependencies per task:`)} ${e.avgDependenciesPerTask.toFixed(1)}\n\n`+w.cyan.bold(`Next Task:`)+`
15
+ ID: ${t?w.cyan(String(t.id)):x.muted(`N/A`)} - ${t?w.bold(t.title):w.yellow(`No task available`)}\nPriority: ${t?.priority||x.muted(`N/A`)} Dependencies: ${t?.dependencies?.length?w.cyan(t.dependencies.join(`, `)):x.muted(`None`)}\nComplexity: ${t?.complexity===void 0?x.muted(`N/A`):V(t.complexity)}`}function xt(e,t,n,r,i){let a=M(),o=a>=120,s=Math.floor(a/2),c=s-4,l=yt(e,t,n,(o?c:a)-8<60),u=bt(r,i);if(o){let e=k(l,{padding:1,borderColor:C,borderStyle:`round`,width:c,dimBorder:!1}),t=k(u,{padding:1,borderColor:C,borderStyle:`round`,width:c,dimBorder:!1}),n=e.split(`
16
+ `),r=t.split(`
17
+ `),i=Math.max(n.length,r.length),a=[];for(let e=0;e<i;e++){let t=e<n.length?n[e]:``,i=e<r.length?r[e]:``,o=t.padEnd(s,` `);a.push(o+i)}console.log(a.join(`
18
+ `))}else{let e=k(l,{padding:1,borderColor:C,borderStyle:`round`,margin:{top:0,bottom:1}}),t=k(u,{padding:1,borderColor:C,borderStyle:`round`,margin:{top:0,bottom:1}});console.log(e),console.log(t)}}const St=[[`done`,`done`],[`in-progress`,`in progress`],[`review`,`review`],[`pending`,`pending`],[`blocked`,`blocked`],[`deferred`,`deferred`],[`cancelled`,`cancelled`]],Ct=e=>e.replace(/\x1b\[[0-9;]*m/g,``).length;function wt(e,t){let n=`Critical path:`,r=[],i=`${n} ${e[0]}`;for(let n of e.slice(1)){let e=` → ${n}`;i.length+e.length>t-2?(r.push(`${i} →`),i=` ${n}`):i+=e}return r.push(i),r.map((e,t)=>t===0?x.muted(n)+e.slice(14):e)}function Tt(e,t={}){let n=t.width??100,r=t.nextId?String(t.nextId):null,i=r?.split(`.`)[0],a=[],o=/* @__PURE__ */ new Set,s=new Map(e.bottlenecks.map(e=>[e.id,e.blocks])),c=new Set(e.criticalPath),l=!1,u=!1,d=(e,t,a)=>{o.add(e.status);let d=e.id===i,f=t=>e.inferred.includes(t),p=e=>f(e)?(u=!0,`${e}*`):e,m=[];e.alsoNeeds.length&&m.push(`needs ${e.alsoNeeds.map(p).join(`, `)}`);let h=s.get(e.id);h!==void 0&&m.push(`blocks ${h}`);let ee=c.has(e.id);ee&&(l=!0);let te=a!==void 0&&f(a);te&&(u=!0);let ne=te?`${x.brand(e.id)}${x.muted(`*`)}`:x.brand(e.id),re=e.missing.length?w.yellow(` · missing ${e.missing.join(`, `)}`):``,ie=(m.length?x.muted(` · ${m.join(` · `)}`):``)+re+(ee?x.brand(` ◆`):``)+(d?x.brand.bold(r===i?` ← next`:` ← next: ${r}`):``),g=`${t}${Ge(e.status)} ${ne} `,ae=Math.max(12,n-Ct(g)-Ct(ie)),_=P(e.title,ae);return g+(d||e.status===`in-progress`?w.bold(_):e.status===`done`||e.status===`cancelled`?x.muted(_):_)+ie},f=(e,t,n,r)=>{a.push(d(e,n+x.muted(r?`└─ `:`├─ `),t.id));let i=n+x.muted(r?` `:`│ `);e.children.forEach((t,n)=>f(t,e,i,n===e.children.length-1))};if(e.roots.forEach((t,n)=>{let r=e.roots[n-1];r&&(r.children.length||t.children.length)&&a.push(``),a.push(d(t,``)),t.children.forEach((e,n)=>f(e,t,``,n===t.children.length-1))}),e.cyclic.length){a.push(``,w.yellow(`⚠ These tasks depend on each other in a loop:`));for(let t of e.cyclic)a.push(d(t,` `));let t=new Set(e.cyclic.map(e=>e.id)),n=e.cyclic[0],r=n.alsoNeeds.find(e=>t.has(e));r&&a.push(x.muted(` Break it with `)+x.brand(`taskgraph remove-dependency --id=${n.id} --depends-on=${r}`))}if(e.bottlenecks.length){let t=Math.max(...e.bottlenecks.map(e=>e.id.length)),r=e.bottlenecks.map(e=>`blocks ${e.blocks}`),i=Math.max(...r.map(e=>e.length)),o=Math.max(12,n-(2+t+2+i+2));a.push(``,x.muted(`Bottlenecks`)),e.bottlenecks.forEach((e,n)=>{a.push(` ${x.brand(e.id.padEnd(t))} ${w.yellow(r[n].padEnd(i))} ${P(e.title,o)}`)})}e.criticalPath.length&&a.push(``,...wt(e.criticalPath,n));let p=St.filter(([e])=>o.has(e)).map(([e,t])=>`${Ge(e)} ${x.muted(t)}`).join(` `);p&&a.push(``,p);let m=[l?`◆ critical path`:``,u?`* dependency inferred by AI`:``].filter(Boolean);return m.length&&a.push(x.muted(m.join(` `))),a}function Et(e){return x.muted(`[tag] ${e}`)}const Dt=(e,t)=>`${e} ${e===1?t:`${t}s`}`,Ot=(e,t)=>e.length>t?`${e.slice(0,Math.max(1,t-1))}…`:e,R=e=>`${w.green(`✓`)} ${e}`,z=(...e)=>{let t=e.filter(Boolean);return t.length?x.muted(` · ${t.join(` · `)}`):``},kt=e=>x.muted(`Switch to it with `)+x.brand(`taskgraph tags use ${e}`);function At(e,t=M()){let n=e.sourceTag&&`${Dt(e.tasksCopied,`task`)} from ${e.sourceTag}`,r=[R(`Created tag ${e.tagName}`)+z(n)];return e.description&&r.push(` ${x.muted(Ot(e.description,t-2))}`),r.push(kt(e.tagName)),r.join(`
19
+ `)}function jt(e,t=M()){let n=Dt(e.taskCount,`task`),r=[e.previousTag===e.currentTag?`Already on ${e.currentTag}${z(n)}`:R(`Switched to ${e.currentTag}`)+z(n)];if(e.nextTask){let n=String(e.nextTask.id),i=Ot(e.nextTask.title,t-8-n.length);r.push(`${x.muted(`Next:`)} ${x.brand(n)} ${i}`)}else e.taskCount===0?r.push(x.muted(`Add tasks with `)+x.brand(`taskgraph add-task`)+x.muted(` or `)+x.brand(`taskgraph parse-prd <file>`)):r.push(x.muted(`No task is ready to start`));return r.join(`
20
+ `)}function Mt(e){return R(`Renamed ${e.oldName} to ${e.newName}`)+z(e.isCurrentTag&&`current tag`)}function Nt(e){return[R(`Copied ${e.sourceName} to ${e.targetName}`)+z(Dt(e.tasksCopied,`task`)),kt(e.targetName)].join(`
21
+ `)}function Pt(e){let t=e.tasksDeleted===0?``:e.tasksDeleted===1?` and its task`:` and its ${e.tasksDeleted} tasks`;return R(`Deleted tag ${e.tagName}${t}`)+z(e.switchedToMaster&&`switched to master`)}function Ft(e,t={},n=M()){if(e.length===0)return t.ready?`No tag has a task ready to start`:`No tags yet`;let r=[`Tasks`,`Ready`,`Done`],i=t.showMetadata?e.map(e=>{let t=new Date(e.created??``);return Number.isNaN(t.getTime())?``:t.toISOString().slice(0,10)}):[],a=t.showMetadata?10:0,o=2+r.reduce((e,t)=>e+2+t.length,0)+(t.showMetadata?2+a:0),s=Math.max(3,...e.map(e=>e.name.length)),c=t.showMetadata?Math.floor((n-o-2)/2):n-o,l=Math.max(8,Math.min(s,c)),u=n-o-l-2,d=t.showMetadata&&u>=8,f=[` `,`Tag`.padEnd(l),...r.map(e=>` ${e}`),t.showMetadata?` ${`Created`.padEnd(a)}`:``,d?` Description`:``].join(``),p=[x.muted(f.trimEnd())];return e.forEach((e,n)=>{let o=e.isCurrent?`${w.green(`●`)} `:` `,s=Ot(e.name,l).padEnd(l),c=[e.taskCount,e.readyTasks,e.completedTasks].map((e,t)=>{let n=String(e).padStart(r[t].length);return` ${e===0?x.muted(n):n}`}),f=`${o}${e.isCurrent?w.bold(s):s}${c.join(``)}`;if(t.showMetadata){let t=e.description&&d?` ${Ot(e.description,u)}`:``,r=t?i[n].padEnd(a):i[n];(r||t)&&(f+=x.muted(` ${r}${t}`))}p.push(f.trimEnd())}),p.join(`
22
+ `)}function It(e={}){let{tag:t}=e;t&&console.log(Et(t))}const Lt=new ze({headingStyle:`atx`,codeBlockStyle:`fenced`,bulletListMarker:`-`});Le.use(Re({code:e=>e.split(`
23
+ `).map(e=>` `+w.cyan(e)).join(`
24
+ `),blockquote:x.muted.italic,html:x.muted,heading:x.text.bold,hr:x.muted,listitem:x.text,paragraph:x.text,strong:x.text.bold,em:x.text.italic,codespan:w.cyan,del:w.dim.strikethrough,link:x.brand,href:x.brand.underline,showSectionPrefix:!1,unescape:!0,emoji:!1,tab:4,width:120})),Le.setOptions({breaks:!0,gfm:!0});function Rt(e){if(!e)return``;let t=e.replace(/\\\\/g,`\\`).replace(/\\n/g,`
25
+ `).replace(/\\t/g,` `).replace(/\\"/g,`"`);return/<[^>]+>/.test(t)?Lt.turndown(t):t}function zt(e){if(!e)return``;let t=Rt(e),n=Le(t);return typeof n==`string`?n.trim():t}const Bt=e=>Math.max(40,Math.min(e??M(),100));function Vt(e,t,n){return e.flatMap(e=>{let r=` ${e.checked?w.green(`✓`):x.muted(`○`)} ${x.brand(String(e.number).padStart(t))} `,i=` `.repeat(4+t+2);return F(`${r}${x.text(e.text)}`,n,i)})}const Ht=e=>Math.max(1,...e.map(e=>String(e.number).length));function Ut(e,t){let n=Bt(t),r=Ht(e.items);return[[`Acceptance criteria`,e.items.filter(e=>e.source===`task`)],[`Definition of Done`,e.items.filter(e=>e.source===`definition-of-done`)]].filter(([,e])=>e.length>0).flatMap(([e,t])=>{let i=t.filter(e=>e.checked).length;return[`${w.bold(e)} ${x.muted(`${i}/${t.length}`)}`,...Vt(t,r,n)]}).join(`
26
+ `)}function Wt(e,t,n){let r=t.items.length,i=`${w.green(`✓`)} Task ${x.brand(e)}`;return t.unchecked.length===0?[`${i} all ${r} checked`,`Next: ${x.brand(`taskgraph set-status ${e} done`)}`].join(`
27
+ `):[`${i} ${t.checkedCount} of ${r} checked`,...Vt(t.unchecked,Ht(t.unchecked),Bt(n))].join(`
28
+ `)}function Gt(e,t,n,r){let i=Bt(r),a=n.map(e=>e.number).join(`,`),o=` ${x.muted(`Check them with`)} ${x.brand(`taskgraph set-status ${t} --check ${a}`)}${x.muted(`, or pass`)} ${x.brand(`--force`)}`;return[`${w.red(`✗`)} ${e}`,...Vt(n,Ht(n),i),...F(o,i,` `)].join(`
29
+ `)}function Kt(e,t,n){let r=String(e),i=r.includes(`.`),a=i?{command:`taskgraph update-subtask --id=${r} --prompt="..."`,description:`to log progress notes`}:{command:`taskgraph update-task --id=${r} --prompt="..."`,description:`to update details`},o=!i&&!n?[{command:`taskgraph expand --id=${r}`,description:`to break down into subtasks`}]:[];switch(t){case`in-progress`:return[a,{command:`taskgraph set-status --id=${r} --status=done`,description:`when it is finished`},...o];case`review`:return[{command:`taskgraph set-status --id=${r} --status=done`,description:`once the review passes`},{command:`taskgraph set-status --id=${r} --status=in-progress`,description:`if it needs more work`}];case`done`:case`completed`:case`cancelled`:return[{command:`taskgraph next`,description:`to find the next task to work on`}];case`blocked`:case`deferred`:return[{command:`taskgraph set-status --id=${r} --status=pending`,description:`when it is ready to pick up again`},a];default:return[{command:`taskgraph set-status --id=${r} --status=in-progress`,description:`to start working`},...o,a]}}function qt(e){switch(e){case`create`:return w.green(`✚ CREATE`);case`modify`:return w.yellow(`✎ MODIFY`);case`reference`:return x.brand(`◇ REFER `);default:return x.muted(` FILE `)}}function Jt(e){return e}function Yt(e,t){console.log(k(w.bold(`Task: #${e} - ${t}`),{padding:{top:0,bottom:0,left:1,right:1},borderColor:C,borderStyle:`round`}))}function Xt(e,t){let n=N(),r=new Be({head:[],style:{head:[],border:ge},colWidths:qe(n,[{key:`label`,width:16},{key:`value`,width:`flex`}]).widths,wordWrap:!0}),i=e.dependencies&&e.dependencies.length>0?e.dependencies.map(e=>String(e)).join(`, `):`None`,a=t||String(e.id),o=zt(e.description||``),s=e.category?`${Jt(e.category)}`:x.muted(`N/A`),c=e.skills&&e.skills.length>0?e.skills.map(e=>x.accent(`[${e}]`)).join(` `):x.muted(`N/A`),l=[w.cyan(`ID:`),w.cyan(`Title:`),w.cyan(`Status:`),w.cyan(`Priority:`),w.cyan(`Dependencies:`),w.cyan(`Complexity:`),w.cyan(`Category:`),w.cyan(`Skills:`),w.cyan(`Description:`)].join(`
30
+ `),u=[a,e.title,A(e.status),Tn(e.priority),i,typeof e.complexity==`number`?V(e.complexity):x.muted(`N/A`),s,c,o].join(`
31
+ `);r.push([l,u]),console.log(r.toString())}function Zt(e){let t=N(),n=zt(e);console.log(k(w.bold(`Implementation Details:`)+`
32
+
33
+ `+n,{padding:1,borderStyle:`round`,borderColor:C,width:t}))}function Qt(e){let t=N(),n=zt(e);console.log(k(w.bold(`Test Strategy:`)+`
34
+
35
+ `+n,{padding:1,borderStyle:`round`,borderColor:C,width:t}))}function $t(e,t){let n=N();console.log(k(x.heading(`Subtasks`),{padding:{top:0,bottom:0,left:1,right:1},borderColor:C,borderStyle:`round`,margin:{top:1,bottom:0}}));let r=new Be({head:[x.heading(`ID`),x.heading(`Status`),x.heading(`Title`),x.heading(`Deps`)],style:{head:[],border:ge},colWidths:qe(n,[{key:`id`,width:10},{key:`status`,width:15},{key:`title`,width:`flex`},{key:`deps`,width:8}]).widths,wordWrap:!0});e.forEach(e=>{let n=t?`${t}.${e.id}`:String(e.id),i=e.dependencies&&e.dependencies.length>0?e.dependencies.join(`, `):`None`;r.push([n,A(e.status),e.title,i])}),console.log(r.toString())}function en(e){let t=N(),n=e.map(e=>`${qt(e.action)} ${x.text(e.path)}\n ${x.muted(e.description)}`).join(`
36
+
37
+ `);console.log(k(w.bold(`Files to Touch:`)+`
38
+
39
+ `+n,{padding:1,borderStyle:`round`,borderColor:`yellow`,width:t}))}function tn(e){let t=N(),n=e.map(e=>`${w.cyan.bold(e.name)} → ${x.muted(e.location)}\n ↳ ${x.text(e.usage)}`).join(`
40
+
41
+ `);console.log(k(w.bold(`Leverage Existing Code:`)+`
42
+
43
+ `+n,{padding:1,borderStyle:`round`,borderColor:C,width:t}))}function nn(e){let t=N(),n=``;e.included&&(n+=w.green.bold(`✓ In Scope:
44
+ `),n+=x.text(` `+e.included)),e.excluded&&(n&&(n+=`
45
+
46
+ `),n+=w.red.bold(`✗ Out of Scope:
47
+ `),n+=x.muted(` `+e.excluded)),console.log(k(w.bold(`Scope Boundaries:`)+`
48
+
49
+ `+n,{padding:1,borderStyle:`round`,borderColor:C,width:t}))}function rn(e){let t=N(),n=e.map(e=>w.yellow(`▸ ${e}`)).join(`
50
+ `);console.log(k(w.bold(`Technical Constraints:`)+`
51
+
52
+ `+n,{padding:1,borderStyle:`round`,borderColor:`red`,width:t}))}function an(e){let t=N(),n=zt(e);console.log(k(w.bold(`Implementation Approach:`)+`
53
+
54
+ `+n,{padding:1,borderStyle:`round`,borderColor:C,width:t}))}function on(e){let t=N(),n=e.map(e=>x.text(`• ${e}`)).join(`
55
+ `);console.log(k(w.bold(`Codebase Patterns:`)+`
56
+
57
+ `+n,{padding:1,borderStyle:`round`,..._e,width:t}))}function sn(e,t){let n=``;e&&(n+=x.muted(`Category: `)+w.cyan(`[${Jt(e)}]`)),t&&t.length>0&&(n&&(n+=` `),n+=x.muted(`Skills: `)+t.map(e=>x.accent(`[${e}]`)).join(` `)),n&&console.log(`
58
+ `+n)}function cn(e,t){let n=t??c(e,[]);n.items.length>0&&(console.log(),console.log(Ut(n))),(e.relevantFiles||e.existingInfrastructure||e.scopeBoundaries||e.technicalConstraints||e.implementationApproach||e.codebasePatterns)&&(e.implementationApproach&&(console.log(),an(e.implementationApproach)),e.relevantFiles&&e.relevantFiles.length>0&&(console.log(),en(e.relevantFiles)),e.existingInfrastructure&&e.existingInfrastructure.length>0&&(console.log(),tn(e.existingInfrastructure)),e.codebasePatterns&&e.codebasePatterns.length>0&&(console.log(),on(e.codebasePatterns)),e.scopeBoundaries&&(console.log(),nn(e.scopeBoundaries)),e.technicalConstraints&&e.technicalConstraints.length>0&&(console.log(),rn(e.technicalConstraints)))}function ln(e,t,n=!1){let r=Kt(e,t,n).map((e,t)=>`${w.cyan(`${t+1}.`)} Run ${w.yellow(e.command)} ${e.description}`);console.log(k(w.bold(`Suggested Actions:`)+`
59
+
60
+ `+r.join(`
61
+ `),{padding:1,margin:{top:1},borderStyle:`round`,borderColor:`green`,width:N()}))}function un(e,t){let{statusFilter:n,showSuggestedActions:r=!1,customHeader:i,headerColor:a=C,originalTaskId:o,spaceAbove:s=!0,checklist:c}=t||{};if(i?console.log(k(w.bold(i),{padding:{top:0,bottom:0,left:1,right:1},borderColor:a,borderStyle:`round`,margin:{top:+!!s}})):Yt(o||e.id,e.title),Xt(e,o),e.details&&(console.log(),Zt(e.details)),`testStrategy`in e&&e.testStrategy&&(console.log(),Qt(e.testStrategy)),cn(e,c),e.subtasks&&e.subtasks.length>0){let t=n?e.subtasks.filter(e=>e.status===n):e.subtasks;t.length===0&&n?(console.log(),console.log(x.muted(` No subtasks with status '${n}'`))):t.length>0&&(console.log(),$t(t,e.id))}r&&(console.log(),ln(o||e.id,e.status,!!(e.subtasks&&e.subtasks.length>0)))}function dn(e,t){if(!e){console.log(t?w.yellow(`✓ All tasks are either completed, blocked by dependencies, or in progress.`):k(w.yellow(`No tasks found in this project.`),{padding:1,borderStyle:`round`,borderColor:`yellow`,title:`No tasks available`,titleAlignment:`center`}));return}let n=[];n.push(`${x.heading(`Next task:`)} ${w.yellow(`#${e.id}`)}${x.heading(` - ${e.title}`)}`),n.push(``);let r=[];if(e.priority){let t=e.priority===`high`?w.red:e.priority===`medium`?w.yellow:x.muted;r.push(`Priority: ${t.bold(e.priority)}`)}if(e.status){let t=e.status===`pending`?w.yellow(`○ pending`):e.status===`in-progress`?x.brand(`▶ in-progress`):x.muted(e.status);r.push(`Status: ${t}`)}n.push(r.join(` `));let i=!e.dependencies||e.dependencies.length===0?x.muted(`None`):w.cyan(e.dependencies.join(`, `));n.push(`Dependencies: ${i}`),typeof e.complexity==`number`&&n.push(`Complexity: ${V(e.complexity)}`),e.description&&(n.push(``),n.push(`Description: ${x.text(zt(e.description))}`)),n.push(``);for(let t of Kt(e.id,e.status,!0).slice(0,2))n.push(`${w.cyan(`Next step:`)} ${w.yellow(t.command)} ${x.muted(t.description)}`);n.push(`${w.cyan(`View details:`)} ${w.yellow(`taskgraph show ${e.id}`)}`),console.log(k(n.join(`
62
+ `),{padding:1,margin:{top:1,bottom:1},borderStyle:`round`,borderColor:C,title:x.heading(`Next task`),titleAlignment:`center`,width:j(.97),fullscreen:!1}))}function fn(e){if(`description`in e&&e.description)return e.description;if(`details`in e&&e.details)return e.details.split(`
63
+ `)[0].split(`.`)[0]}const pn=[`⠋`,`⠙`,`⠹`,`⠸`,`⠼`,`⠴`,`⠦`,`⠧`,`⠇`,`⠏`];function mn(e=w.hex(be.accent)){return{interval:80,frames:pn.map(t=>e(t))}}function B(e={}){let t=Ve({...typeof e==`string`?{text:e}:e,spinner:mn(),color:!1}),n=e=>n=>t.stopAndPersist({symbol:e,text:n});return t.succeed=n(w.green(`✓`)),t.fail=n(w.red(`✗`)),t.warn=n(w.yellow(`⚠`)),t}function hn(e,t=!1){let n=e?.tasks?.length??0;return t?n:Math.max(0,n-1)}function gn(e){let t=Math.max(0,Math.floor(e/1e3));return`${Math.floor(t/60)}:${String(t%60).padStart(2,`0`)}`}function _n(e){let t=Math.max(0,Math.round(e/1e3)),n=Math.floor(t/60),r=t%60;return n===0?`${r}s`:r?`${n}m ${r}s`:`${n}m`}function vn(e,t){let n=e.replace(/\s+/g,` `).trim();return n.length>t?`${n.slice(0,t-1).trimEnd()}…`:n}var yn=class{options;spinner;ticker;startedAt=0;printed=0;current;interactive;constructor(e){this.options={numTasks:e.numTasks||0,startId:e.startId??1,research:e.research??!1,stream:e.stream??process.stdout,now:e.now??Date.now,prdName:e.prdName},this.interactive=!!this.options.stream.isTTY}start(){return this.startedAt=this.options.now(),this.interactive?(this.spinner=B({text:this.statusText(),stream:this.options.stream}).start(),this.ticker=setInterval(()=>this.refresh(),1e3),this.ticker.unref?.()):this.write(`${this.statusText()}\n`),this}update(e){this.current=e,this.printCompleted(hn(e)),this.refresh()}succeed(e){e&&(this.current=e),this.printCompleted(hn(this.current,!0));let t=this.printed,n=_n(this.options.now()-this.startedAt),r=`${t} ${t===1?`task`:`tasks`} in ${n}`;this.stop(),this.write(`${w.green(`✓`)} ${w.bold(r)}\n`)}fail(e){this.stop(),this.write(`${w.red(`✗`)} ${e}\n`)}stop(){this.ticker&&clearInterval(this.ticker),this.ticker=void 0,this.spinner?.stop(),this.spinner=void 0}get printedCount(){return this.printed}printCompleted(e){let t=this.current?.tasks??[];for(;this.printed<e;){let e=t[this.printed],n=this.options.startId+this.printed,r=vn(e?.title??``,Math.max(20,this.columns-7));this.persist(`${w.green(`✓`)} ${x.brand(String(n).padEnd(3))}${r}`),this.printed++}}persist(e){this.spinner?(this.spinner.clear(),this.write(`${e}\n`),this.spinner.render()):this.write(`${e}\n`)}refresh(){this.spinner&&(this.spinner.text=this.statusText())}statusText(){let{numTasks:e,prdName:t,research:n}=this.options,r=this.current?.tasks?.length??0,i;if(r===0)i=e?`Reading ${t} and planning ${e} tasks`:`Reading ${t} and planning tasks`,n&&(i+=` with research`);else{let t=e?` of ${e}`:``,n=this.current?.tasks?.[r-1]?.title;i=`Writing task ${r}${t}`;let a=this.columns-2-i.length-3-2-6;n&&a>=12&&(i+=x.muted(` · ${vn(n,a)}`))}return`${i} ${x.muted(this.elapsed())}`}get columns(){return M(this.options.stream)}elapsed(){return gn(this.options.now()-this.startedAt)}write(e){this.options.stream.write(e)}};function bn(){let e=[`${w.cyan(`1.`)} Run ${w.yellow(`taskgraph next`)} to see what to work on next`,`${w.cyan(`2.`)} Run ${w.yellow(`taskgraph expand --id=<id>`)} to break down a task into subtasks`,`${w.cyan(`3.`)} Run ${w.yellow(`taskgraph set-status --id=<id> --status=done`)} to mark a task as complete`];console.log(k(w.bold(`Suggested Next Steps:`)+`
64
+
65
+ `+e.join(`
66
+ `),{padding:1,margin:{top:0,bottom:1},borderStyle:`round`,..._e,width:j(.97)}))}const xn=`tasks.json`;function Sn(e){let t=ee(e);console.log(w.dim(`\nWatching ${xn} for changes...`)),console.log(x.muted(`Last synced: ${t}`)),console.log(w.dim(`Press Ctrl+C to exit`))}function Cn(e){let t=ee(e);console.log(x.brand(`\nℹ ${xn} updated at ${t}`))}const wn={critical:w.red.bold,high:w.red,medium:w.yellow,low:x.muted};function Tn(e){return(wn[e]||x.text)(e)}function En(e){return e>=7?`High`:e>=4?`Medium`:`Low`}function Dn(e){let t=En(e);return{color:t===`High`?w.red:t===`Medium`?w.yellow:w.green,label:t}}function V(e){let t=typeof e==`string`?Number(e.trim()):e;if(isNaN(t))return x.muted(`N/A`);let{color:n}=Dn(t);return n(`● ${t}`)}function On(e){if(typeof e!=`number`)return x.muted(`N/A`);let{color:t,label:n}=Dn(e);return t(`${e}/10 (${n})`)}const kn=(e,t)=>`${e} ${e===1?t:`${t}s`}`,An=(e,t)=>e.length>t?`${e.slice(0,Math.max(1,t-1))}…`:e,jn=e=>[...e].sort((e,t)=>t.complexityScore-e.complexityScore);function Mn(e,t){let n=[],r=``;for(let i of e.split(/\s+/).filter(Boolean))r&&r.length+1+i.length>t?(n.push(r),r=i):r=r?`${r} ${i}`:i;return r&&n.push(r),n}function Nn(e,t){let n=jn(e),r=Math.max(...n.map(e=>String(e.taskId).length)),i=Math.max(...n.map(e=>String(e.complexityScore).length)),a=e=>e.recommendedSubtasks?kn(e.recommendedSubtasks,`subtask`):``,o=Math.max(0,...n.map(e=>a(e).length)),s=Math.max(12,Math.min(Math.max(...n.map(e=>e.taskTitle.length)),t-2-r-2-2-(i+2)-(o?o+2:0)));return n.map(e=>{let t=An(e.taskTitle,s).padEnd(s),n=V(e.complexityScore),o=` `.repeat(i-String(e.complexityScore).length),c=a(e);return{item:e,line:` ${x.brand(String(e.taskId).padEnd(r))} ${t} ${n}${o}${c?` ${x.muted(c)}`:``}`.trimEnd(),indent:2+r+2}})}function Pn(e){let t={High:0,Medium:0,Low:0};for(let n of e)t[En(n.complexityScore)]++;return`High ${t.High} · Medium ${t.Medium} · Low ${t.Low}`}const Fn=()=>x.muted(`Run `)+x.brand(`taskgraph expand --id=<id>`)+x.muted(` or `)+x.brand(`--all`)+x.muted(` to use these recommendations`);function In(e,t=M()){let{analyses:n,skipped:r,kept:i,reportPath:a}=e;if(n.length===0)return x.muted(`No pending tasks to analyze`);let o=[e.usedResearch?`with web research`:null,r>0?`skipped ${r} done`:null].filter(Boolean),s=[`${w.green(`✓`)} Analyzed ${kn(n.length,`task`)}${o.length?x.muted(` · ${o.join(` · `)}`):``}`,...Nn(n,t).map(e=>e.line)],c=i===0?``:`, with ${i} earlier ${i===1?`analysis`:`analyses`}`;return s.push(x.muted(`Saved to ${a}${c}`)),s.push(x.muted(`Next: `)+x.brand(`taskgraph expand --all`)+x.muted(`, or `)+x.brand(`taskgraph complexity-report`)+x.muted(` to see why`)),s.join(`
67
+ `)}function Ln(e,t=M()){let n=e.complexityAnalysis??[];if(n.length===0)return x.muted(`The report has no analyzed tasks yet`);let r=new Date(e.meta.generatedAt),i=Number.isNaN(r.getTime())?null:r.toLocaleString(void 0,{month:`short`,day:`numeric`,hour:`numeric`,minute:`2-digit`}),a=[kn(n.length,`task`),Pn(n),e.meta.usedResearch?`with web research`:null,i].filter(Boolean).join(` · `),o=[x.heading(`Complexity report`),x.muted(a),``];for(let e of Nn(n,t)){if(o.push(e.line),e.item.reasoning){let n=` `.repeat(e.indent);for(let r of Mn(e.item.reasoning,Math.max(20,t-e.indent)))o.push(x.muted(`${n}${r}`))}o.push(``)}return o.push(Fn()),o.join(`
68
+ `)}const Rn=(e,t)=>Math.round(e).toLocaleString(t);function zn(e,t=`USD`,n){let r=(e,r)=>{try{return new Intl.NumberFormat(n,{style:`currency`,currency:t,...r}).format(e)}catch{return`${t} ${e.toFixed(2)}`}};return e<.01?`<${r(.01,{maximumFractionDigits:2})}`:e<1?r(e,{maximumSignificantDigits:3}):r(e,{maximumFractionDigits:2,minimumFractionDigits:2})}function Bn(e,t){if(!e)return null;let n=e.inputTokens??0,r=e.outputTokens??0,i=e.totalTokens||n+r;if(!i)return null;let a=[],o=e.modelUsed;o&&a.push(o===`Multiple`?`several models`:o),a.push(`${Rn(i,t)} ${i===1?`token`:`tokens`} (${Rn(n,t)} in, ${Rn(r,t)} out)`);let s=e.cachedInputTokens??0;return n>0&&s/n>=.01&&a.push(`${Math.round(s/n*100)}% cached`),!e.isUnknownCost&&(e.totalCost??0)>0&&a.push(`~${zn(e.totalCost,e.currency,t)}`),a.join(` · `)}const Vn=e=>e.oldStatus===e.newStatus?`${A(e.newStatus)} ${x.muted(`(unchanged)`)}`:`${A(e.oldStatus)} → ${A(e.newStatus)}`;function Hn(e){let t=w.green(`✓`);if(e.length===1){let[n]=e;return`${t} Task ${x.brand(n.taskId)} ${Vn(n)}`}let n=Math.max(0,...e.map(e=>e.taskId.length));return[`${t} Updated ${e.length} tasks`,...e.map(e=>` ${x.brand(e.taskId.padEnd(n))} ${Vn(e)}`)].join(`
69
+ `)}const Un=(e,t)=>e.length>t?`${e.slice(0,Math.max(0,t-1))}…`:e;function Wn(e,t){if(!e)return t.hasAnyTasks?[`Nothing ready to claim`,x.muted(`Run ${x.brand(`taskgraph list`)} to see what's in progress or blocked`)].join(`
70
+ `):[`No tasks to claim`,x.muted(`Create some with ${x.brand(`taskgraph parse-prd`)} or ${x.brand(`taskgraph add-task`)}`)].join(`
71
+ `);let n=t.width??80,r=e.taskId.includes(`.`)?`subtask`:`task`,i=`Claimed ${r} ${e.taskId} `,a=Un(e.title,n-2-i.length);return[`${w.green(`✓`)} Claimed ${r} ${x.brand(e.taskId)} ${a}`,` ${A(`in-progress`)} ${x.muted(`· claimed by ${e.claimedBy}`)}`,`Next: ${x.brand(`taskgraph show ${e.taskId}`)}`].join(`
72
+ `)}function Gn(e,t,n=M()){let r=t.length,i=r===1?`subtask`:`subtasks`,a=[`${w.green(`✓`)} Added ${r} ${i} to task ${e}`],o=t.map(t=>`${e}.${t.id}`),s=Math.max(0,...o.map(e=>e.length)),c=Math.max(10,n-s-4);return t.forEach((e,t)=>{let n=e.title.length>c?`${e.title.slice(0,c-1)}…`:e.title;a.push(` ${x.brand(o[t].padEnd(s))} ${n}`)}),a.join(`
73
+ `)}const Kn=`stephennmiller/taskgraph-ai`,qn=`taskgraph@taskgraph`,Jn=e=>e.replace(/`([^`]+)`/g,(e,t)=>x.brand(t));function Yn(e){let t=Math.max(0,...e.map(e=>e.path.length));return e.map(e=>` ${e.path.padEnd(t)} ${x.muted(Jn(e.note))}`)}function Xn(e){let t=[];return e.claudeCode&&t.push([`Add the slash commands in Claude Code:`,x.brand(`/plugin marketplace add ${Kn}`),x.brand(`/plugin install ${qn}`)]),e.alreadySetUp||t.push([`Write a PRD in .taskgraph/docs/prd.md`,x.muted(`Templates are in .taskgraph/templates/`)],[`Turn it into tasks: ${x.brand(`taskgraph parse-prd`)}`],[`Start the first task: ${x.brand(`taskgraph next`)}`]),t}function Zn(e){let t=w.green(`✓`),n=[];e.alreadySetUp?e.changes.length>0?n.push(`${t} Updated TaskGraph in ${e.folder}`):(n.push(`${t} TaskGraph is already set up in ${e.folder}`),n.push(x.muted(Jn(" Run `taskgraph list` to see your tasks")))):n.push(`${t} Set up TaskGraph in ${e.folder}`),n.push(...Yn(e.changes));let r=Xn(e);return r.length>0&&(n.push(``,x.heading(`Next steps`)),r.forEach(([e,...t],r)=>{let i=`${r+1}. `;n.push(` ${i}${e}`);for(let e of t)n.push(` ${` `.repeat(i.length)}${e}`)})),e.alreadySetUp||(n.push(``,x.muted(Jn("AI runs through Claude Code; run `claude` once to sign in"))),e.defaultModels&&n.push(x.muted(Jn("Using the default models; change them with `taskgraph models --setup`")))),n.join(`
74
+ `)}const Qn=[{title:`Daily workflow`,commands:[{name:`next`,desc:`Show the next task to work on`},{name:`show`,desc:`Show one task in detail`},{name:`list`,desc:`List tasks, filtered by status or tag`},{name:`set-status`,desc:`Change a task or subtask status`},{name:`add-task`,desc:`Add a task from a description`}]},{title:`Setup`,commands:[{name:`init`,desc:`Set up TaskGraph in this project`},{name:`models`,desc:`View or change the AI models`},{name:`completion`,desc:`Install Tab completion for your shell`}]},{title:`Create & update`,commands:[{name:`parse-prd`,desc:`Generate tasks from a PRD`},{name:`generate`,desc:`Write a file for each task`},{name:`update`,desc:`Update tasks from an ID onwards`},{name:`update-task`,desc:`Update one task`},{name:`update-subtask`,desc:`Add notes to a subtask`},{name:`add-subtask`,desc:`Add a subtask, or make a task one`},{name:`remove-task`,desc:`Remove a task or subtask`},{name:`remove-subtask`,desc:`Remove a subtask`},{name:`clear-subtasks`,desc:`Remove all subtasks from tasks`},{name:`sync-readme`,desc:`Export tasks to README.md`}]},{title:`Analyze & expand`,commands:[{name:`analyze-complexity`,desc:`Score tasks for complexity`},{name:`complexity-report`,desc:`Show the complexity report`},{name:`expand`,desc:`Break a task into subtasks`},{name:`research`,desc:`Ask a research question about the project`}]},{title:`Organize`,commands:[{name:`tags <add|use|remove|rename|copy>`,desc:`List or manage tags`},{name:`graph`,desc:`Show tasks as a dependency tree`},{name:`why`,desc:`Explain why a task is blocked`},{name:`add-dependency`,desc:`Make a task depend on another`},{name:`remove-dependency`,desc:`Remove a dependency`},{name:`validate-dependencies`,desc:`Report invalid dependencies`},{name:`fix-dependencies`,desc:`Fix invalid dependencies`}]}],$n=(e,t)=>e.length>t?`${e.slice(0,Math.max(1,t-1))}…`:e;function er(e=M()){let t=Qn.flatMap(e=>e.commands),n=Math.max(...t.map(e=>e.name.length)),r=Math.max(10,e-4-n-2),i=[`${w.bold(`TaskGraph`)} ${x.muted(`AI task management for your coding agent`)}`];for(let e of Qn){i.push(``,x.heading(e.title));for(let t of e.commands)i.push(` ${x.brand(t.name.padEnd(n))} ${x.muted($n(t.desc,r))}`)}return i.push(``,x.muted(`Run `)+x.brand(`taskgraph <command> --help`)+x.muted(` for a command’s flags`),x.muted(`Agents: `)+x.brand(`taskgraph prime`)+x.muted(` prints task context and rules`),x.muted(`The CLI works on its own. For Claude Code slash commands:`),` ${x.brand(`/plugin marketplace add ${Kn}`)}`,` ${x.brand(`/plugin install ${qn}`)}`),i.join(`
75
+ `)}function tr(e){return e==null?``:Oe(String(e)).replace(/[\u0000-\u0008\u000b-\u001f\u007f-\u009f]/g,``)}const nr=(e,t)=>e.length>t?`${e.slice(0,Math.max(1,t-1)).trimEnd()}…`:e,rr=e=>Oe(e).length;function ir(e,t){return e.split(`
76
+ `).flatMap(e=>{let n=e.replace(/^(\s*)\* /,`$1• `),r=Oe(n).match(/^(\s*)(•|\d+\.)\s+/);return!r||rr(n)<=t?[n]:F(n,t,` `.repeat(r[0].length))}).join(`
77
+ `)}function ar(e,t,n={}){let r=new Ie({gfm:!0,breaks:n.breaks??!1});return r.use(Re({code:e=>e.split(`
78
+ `).map(e=>w.cyan(e)).join(`
79
+ `),blockquote:x.muted.italic,html:x.muted,heading:x.text.bold,firstHeading:x.text.bold,hr:x.muted,listitem:x.text,paragraph:x.text,strong:x.text.bold,em:x.text.italic,codespan:w.cyan,del:w.dim.strikethrough,link:x.brand,href:x.brand.underline,showSectionPrefix:!1,unescape:!0,emoji:!1,tab:2,width:t,reflowText:!0})),r.use({renderer:{text(e){return typeof e==`object`&&`tokens`in e&&e.tokens?this.parser.parseInline(e.tokens):typeof e==`string`?e:e.text}}}),ir(r.parse(e.trim(),{async:!1}).trimEnd(),t)}function or(e,t=M()){let n=Math.max(40,Math.min(t,100));return ar(e.replace(/<think>[\s\S]*?<\/think>/g,``).trim(),n)}function sr(e){let t=e=>e.split(`.`).map(e=>Number.parseInt(e,10));return[...e].sort((e,n)=>{let[r,i]=[t(e),t(n)];for(let e=0;e<Math.max(r.length,i.length);e++){let t=(r[e]??-1)-(i[e]??-1);if(t!==0)return t}return 0})}const cr=e=>`${e.length===1?`task`:`tasks`} ${sr(e).join(`, `)}`;function lr(e){let t=[],{taskIds:n,relatedTaskIds:r,files:i}=e;return n.length>0&&t.push(cr(n)),r.length>0&&t.push(n.length>0?`related ${sr(r).join(`, `)}`:`related ${cr(r)}`),i.length>0&&t.push(i.length<=2?i.join(`, `):`${i.length} files`),e.projectTree&&t.push(`project tree`),e.customContext&&t.push(`your notes`),t.length===0?``:x.muted(`Context: ${t.join(` · `)}`)}function ur(e){let t=e.kind===`file`?e.path:`${e.id.includes(`.`)?`subtask`:`task`} ${e.id}`;return`${w.green(`✓`)} Saved to ${t}`}function dr(e,t){let n=e.kind===`file`?`a file`:`${e.id.includes(`.`)?`subtask`:`task`} ${e.id}`;return`${w.red(`✗`)} Couldn't save to ${n}: ${t}`}const fr=(e,t)=>e.length>t?`${e.slice(0,Math.max(1,t-1))}…`:e;function pr(e,t,n){let r=Math.max(10,n-e.length-4);return`${w.green(`✓`)} ${e} ${fr(t,r)}`}function mr(e,t){let n=`taskgraph show ${e}`,r=` to see what changed`,i=`Run ${n}${r}`.length<=t;return x.muted(`Run `)+x.brand(n)+(i?x.muted(r):``)}function hr(e,t=M()){return[pr(`Updated task ${e.id}`,e.title,t),mr(e.id,t)].join(`
80
+ `)}function gr(e,t,n=M()){let r=`${e.kind} ${e.id}`;if(!t.trim())return`${w.yellow(`⚠`)} Nothing added to ${r}: the AI returned no text`;let i=n-2>=40?` `:``,a=or(t,n-i.length).split(`
81
+ `).map(e=>e&&`${i}${e}`).join(`
82
+ `);return`${pr(`Added notes to ${r}`,e.title,n)}\n${a}`}function _r(e,t=M()){if(e.length===0)return`No tasks changed: the AI returned none of the tasks it was sent`;if(e.length===1)return hr(e[0],t);let n=e.map(e=>String(e.id)),r=Math.max(...n.map(e=>e.length)),i=Math.max(10,t-r-4),a=[`${w.green(`✓`)} Updated ${e.length} tasks`];return e.forEach((e,t)=>{a.push(` ${x.brand(n[t].padEnd(r))} ${fr(e.title,i)}`)}),a.push(mr(`<id>`,t)),a.join(`
83
+ `)}function vr(e){return[`No tasks to update: none from ${e} on are unfinished`,x.muted(`Run `)+x.brand(`taskgraph list`)+x.muted(` to see task IDs`)].join(`
84
+ `)}function yr(e,t=M()){let n=[`Saved to ${e.tasksPath}`];e.total>e.added&&n.push(`${e.total} tasks in total`),e.research&&n.push(`research-backed`);let r=76<=t?x.muted(`Next: `)+x.brand(`taskgraph next`)+x.muted(` to pick a task, or `)+x.brand(`taskgraph expand --all`)+x.muted(` to split them`):x.muted(`Next: `)+x.brand(`taskgraph next`)+x.muted(` to pick a task`);return[x.muted(n.join(` · `)),r].join(`
85
+ `)}const br=(e,t)=>`${e} ${e===1?t:`${t}s`}`;function xr(e){let{expandedCount:t,skippedCount:n,failedCount:r,tasksToExpand:i,alreadyExpandedCount:a=0}=e;if(i===0)return a===0?`No pending tasks to expand`:[`No pending tasks to expand: ${a===1?`1 already has subtasks`:`${a} already have subtasks`}`,x.muted(`Add `)+x.brand(`--force`)+x.muted(` to replace their subtasks`)].join(`
86
+ `);let o=n>0?x.muted(` · ${n} skipped`):``;if(t===0)return r>0?`${w.red(`✗`)} Couldn't expand ${br(r,`task`)}${o}`:[`No tasks expanded${x.muted(` · ${n} skipped by the complexity report`)}`,x.muted(`Add `)+x.brand(`--num=<n>`)+x.muted(` to expand them anyway`)].join(`
87
+ `);let s=r>0?x.muted(` · `)+w.red(`${r} failed`):``;return[`${w.green(`✓`)} Expanded ${br(t,`task`)}${o}${s}`,x.muted(`Next: `)+x.brand(`taskgraph next`)].join(`
88
+ `)}const H=(e,t)=>e.length>t?`${e.slice(0,Math.max(1,t-1))}…`:e,Sr=e=>e.replace(/\s+/g,` `).trim();function Cr(e,t,n){let r=[],i=``;for(let n of Sr(e).split(` `))i?i.length+1+n.length<=t?i+=` ${n}`:(r.push(i),i=n):i=n;if(i&&r.push(i),r.length<=n)return r.map(e=>H(e,t));let a=r.slice(0,n);return a[n-1]=H(`${a[n-1]} …`,t),a.map(e=>H(e,t))}function wr(e,t,n){let r=e.id.padEnd(t),i=e.parentTitle?` · in ${Sr(e.parentTitle)}`:``,a=n-2-t-2,o=Sr(e.title);if(o.length+i.length<=a)return` ${x.brand(r)} ${o}${x.muted(i)}`;let s=Math.max(10,a-Math.min(i.length,20)),c=H(o,s),l=i?H(i,Math.max(0,a-c.length)):``;return` ${x.brand(r)} ${c}${x.muted(l)}`}function Tr(e,t=process.stdout.columns||80){let{counts:n}=e,r=[`TaskGraph tracks work in this project ${x.muted(`· tag ${e.tag} · ${n.done} of ${n.total} ${n.total===1?`task`:`tasks`} done`)}`];return n.total===0?r.push(``,`No tasks yet. Add some with:`,` ${x.brand(`taskgraph parse-prd <file>`)}${x.muted(` or `)}${x.brand(`taskgraph add-task --prompt="<task>"`)}`):(r.push(``,...Er(e,t)),r.push(``,...Dr(e,t))),r.push(``,x.heading(`Rules`)),e.rules.forEach((e,n)=>{let i=`${n+1}. `,a=` `.repeat(i.length);r.push(` ${i}${H(e.text,t-2-i.length)}`,` ${a}${x.brand(H(e.command,t-2-a.length))}`)}),n.total>0&&r.push(``,`${x.muted(`Next:`)} ${x.brand(`taskgraph show <id>`)} ${x.muted(`for a task’s full details`)}`),r.join(`
89
+ `)}function Er(e,t){if(e.inProgress.length===0)return[x.muted(e.ready.length>0?`Nothing in progress. Claim a ready task first.`:`Nothing in progress.`)];let n=e.inProgress.slice(0,2),r=Math.max(...n.map(e=>e.id.length)),i=` `+` `.repeat(r+2),a=t-i.length-2,o=[x.heading(`In progress`)],s=Math.floor(6/n.length);for(let e of n){if(o.push(wr(e,r,t)),e.doneWhen.length===0){o.push(`${i}${x.muted(`No done-when criteria. Ask, or add a test strategy.`)}`);continue}o.push(`${i}${x.muted(`Done when:`)}`);let n=0,c=0;for(let t of e.doneWhen){let e=Cr(t,a,3);if(n+e.length>s)break;e.forEach((e,t)=>{o.push(`${i}${t===0?`- `:` `}${e}`)}),n+=e.length,c++}let l=e.doneWhen.length-c;l>0&&o.push(`${i}${x.muted(H(`${l} more: taskgraph show ${e.id}`,a+2))}`)}let c=e.inProgress.length-n.length;return c>0&&o.push(` ${x.muted(H(`${c} more in progress: taskgraph list --status=in-progress`,t-2))}`),o}function Dr(e,t){if(e.ready.length===0){let t=e.counts.done===e.counts.total;return[x.muted(t?`All tasks are done.`:`Nothing else is ready. See what blocks it: taskgraph graph`)]}let n=Math.max(...e.ready.map(e=>e.id.length));return[x.heading(`Ready next`),...e.ready.map(e=>wr(e,n,t))]}const Or=(e,t)=>`${e} ${e===1?t:`${t}s`}`,kr=(e,t)=>e.length>t?`${e.slice(0,Math.max(1,t-1))}…`:e;function Ar(e){return e.length===1?`Task ${e[0]} had no subtasks`:e.length<=3?`Tasks ${`${e.slice(0,-1).join(`, `)} and ${e.at(-1)}`} had no subtasks`:`${e.length} tasks had no subtasks`}function jr(e,t=M()){let{cleared:n,empty:r}=e;if(n.length===0)return r.length===1?`Task ${r[0].id} has no subtasks`:`No subtasks to clear`;let i=n.reduce((e,t)=>e+t.count,0),a=n.length===1?`task ${n[0].id}`:Or(n.length,`task`),o=[`${w.green(`✓`)} Cleared ${Or(i,`subtask`)} from ${a}`],s=n.map(e=>String(e.id)),c=Math.max(...s.map(e=>e.length)),l=n.length>1?n.map(e=>Or(e.count,`subtask`)):[],u=Math.max(0,...l.map(e=>e.length)),d=Math.max(10,t-4-c-(u?u+2:0));n.forEach((e,t)=>{let n=l.length?`${x.muted(l[t].padEnd(u))} `:``;o.push(` ${x.brand(s[t].padEnd(c))} ${n}${kr(e.title,d)}`)}),r.length>0&&o.push(x.muted(Ar(r.map(e=>e.id))));let f=n.length===1?String(n[0].id):`<id>`;return o.push(x.muted(`Run `)+x.brand(`taskgraph expand --id=${f}`)+x.muted(` to add new ones`)),o.join(`
90
+ `)}function Mr(e){return typeof e==`string`?tr(e):Array.isArray(e)?e.map(Mr):e&&typeof e==`object`&&!(e instanceof Date)?Object.fromEntries(Object.entries(e).map(([e,t])=>[e,Mr(t)])):e}const Nr=e=>e.length<=1?e.join(``):`${e.slice(0,-1).join(`, `)} and ${e.at(-1)}`,Pr=e=>`parentId`in e&&e.parentId!==void 0;function Fr(e){let t=e.dependencies??[];return Pr(e)?t.map(t=>se(e.parentId,t)):t.map(String)}function Ir(e,t,n=` `){return F(e,t-n.length,``).map(e=>n+e)}function Lr(e,t,n=` `){let r=Math.max(20,t-n.length);return ar(Rt(e),r,{breaks:!0}).split(`
91
+ `).map(e=>e.trim()?n+e:``)}function Rr(e,t,n){let r=`${e} `,[i,...a]=F(t,n-r.length,``),o=` `.repeat(r.length);return[x.brand.bold(e)+` `+w.bold(i),...a.map(e=>o+w.bold(e))]}function zr(e,t){let n=[],r=``;for(let i of e){let e=r?`${r}${x.muted(` · `)}${i}`:i;r&&rr(e)>t?(n.push(r),r=i):r=e}return r&&n.push(r),n}function Br(e,t){let n=[A(e.status)];if(e.priority&&n.push(`${Tn(e.priority)} priority`),typeof e.complexity==`number`){let t=En(e.complexity).toLowerCase();n.push(x.muted(`complexity ${e.complexity} (${t})`))}let r=Fr(e);return r.length>0&&n.push(x.muted(`depends on ${Nr(r)}`)),e.category&&n.push(x.muted(e.category)),e.skills&&e.skills.length>0&&n.push(x.accent(e.skills.join(`, `))),zr(n,t)}const U=(e,t)=>x.heading(e)+(t?x.muted(` · ${t}`):``);function Vr(e,t){let n=(e.relevantFiles??[]).map(e=>({path:e.path??``,action:e.action??``,description:e.description})),r=Math.max(...n.map(e=>e.path.length)),i=Math.max(...n.map(e=>e.action.length)),a=2+i+2;return n.flatMap(e=>{let n=e.action.padEnd(i),o=` ${x.muted(n)} `,s=t-a-r-2;return e.description?s>=20?[`${o}${x.text(e.path.padEnd(r))} ${x.muted(nr(e.description,s))}`]:[o+x.text(e.path),...Ir(e.description,t,` `.repeat(a)).map(e=>x.muted(e))]:[o+x.text(e.path)]})}function Hr(e,t){return(e.existingInfrastructure??[]).flatMap(e=>[` ${x.text(e.name??``)} ${x.muted(e.location??``)}`,...e.usage?Ir(e.usage,t,` `.repeat(2)):[]])}function Ur(e,t,n){let r=` `.repeat(2+t.length+1);return e.flatMap(e=>F(` ${t} ${e}`,n,r))}function Wr(e,t){let n=e.scopeBoundaries;if(!n)return[];let r=[],i=` `.repeat(7);return n.included&&r.push(...F(` In ${n.included}`,t,i)),n.excluded&&r.push(...F(` Out ${n.excluded}`,t,i).map(e=>x.muted(e))),r}function Gr(e,t,n){let r=t.map(t=>{let n=String(t.id).includes(`.`)?String(t.id):`${e}.${t.id}`,r=(t.dependencies??[]).map(t=>se(e,t));return{id:n,status:t.status,statusText:`x ${t.status}`,title:t.title,after:r.length>0?`after ${r.join(`, `)}`:``}}),i=Math.max(...r.map(e=>e.id.length)),a=Math.max(...r.map(e=>e.statusText.length)),o=Math.max(...r.map(e=>e.after.length)),s=2+i+2+a+2,c=o>0&&n-s-o-2>=20,l=Math.max(10,n-s-(c?o+2:0)),u=Math.min(l,Math.max(...r.map(e=>e.title.length)));return r.flatMap(e=>{let t=A(e.status)+` `.repeat(a-e.statusText.length),n=nr(e.title,u),r=` ${x.brand(e.id.padEnd(i))} ${t} ${n}`;return e.after?c?[`${r}${` `.repeat(u-n.length)} ${x.muted(e.after)}`]:[r,x.muted(` `.repeat(s)+e.after)]:[r]})}function Kr(e,t,n,r){if(n){let i=t.filter(e=>e.status===n);return i.length===0?[x.muted(`No ${n} subtasks`)]:[U(`Subtasks`,`${i.length} of ${t.length} ${n}`),...Gr(e,i,r)]}let i=t.filter(e=>e.status===`done`||e.status===`completed`).length;return[U(`Subtasks`,`${i} of ${t.length} done`),...Gr(e,t,r)]}function qr(e,t,n,r){let[i]=Kt(e,t,n);return i?F(`Next: ${x.brand(i.command)} ${i.description}`,r,` `):[]}function Jr(e,t={}){let n=Mr(e),r=Math.max(30,Math.min(t.width??M(),100)),i=t.id??String(n.id),a=i.includes(`.`)?`Subtask ${i}`:`Task ${i}`,o=[];o.push([...Rr(a,n.title,r),...Br(n,r)]),n.description&&o.push(Lr(n.description,r,``));let s=[[`Details`,n.details],[`Test strategy`,n.testStrategy],[`Approach`,n.implementationApproach]];for(let[e,t]of s)t?.trim()&&o.push([U(e),...Lr(t,r)]);n.relevantFiles?.length&&o.push([U(`Files`),...Vr(n,r)]),n.existingInfrastructure?.length&&o.push([U(`Existing code`),...Hr(n,r)]),n.codebasePatterns?.length&&o.push([U(`Patterns`),...Ur(n.codebasePatterns,`•`,r)]),(n.scopeBoundaries?.included||n.scopeBoundaries?.excluded)&&o.push([U(`Scope`),...Wr(n,r)]),n.technicalConstraints?.length&&o.push([U(`Constraints`),...Ur(n.technicalConstraints,`•`,r)]);let l=Mr(t.checklist??c(e,[]));l.items.length>0&&o.push([Ut(l,r)]);let u=Pr(n)?[]:n.subtasks??[];u.length>0&&o.push(Kr(String(n.id),u,t.statusFilter,r));let d=qr(i,n.status,u.length>0,r);return d.length>0&&o.push(d),o.map(e=>e.join(`
92
+ `)).join(`
93
+
94
+ `)}function Yr(e,t=M()){let n=e=>e.map(e=>({...e,title:tr(e.title)})),r={...e,title:tr(e.title),dependencies:n(e.dependencies),unused:e.unused&&n(e.unused)},i=[],a=r.priority?x.muted(` · ${r.priority} priority`):``,o=a?` · ${r.priority} priority`.length:0,s=`✓ Added task ${r.id} `,c=nr(r.title,Math.max(10,t-s.length-o));i.push(`${w.green(`✓`)} Added task ${x.brand(String(r.id))} ${c}${a}`);let l=[[`Depends on`,r.dependencies],[`Not used`,r.unused??[]]],u=l.flatMap(([,e])=>e);if(u.length>0){let e=Math.max(...l.filter(([,e])=>e.length).map(([e])=>e.length)),n=Math.max(...u.map(e=>String(e.id).length)),r=u.some(e=>e.addedByAi),a=2+e+2+n+2,o=Math.max(10,t-a-(r?13:0)),s=Math.min(o,Math.max(...u.map(e=>(e.title||`unknown task`).length)));for(let[t,r]of l)r.forEach((r,a)=>{let o=nr(r.title||`unknown task`,s),c=` ${(a===0?t:``).padEnd(e)} ${x.brand(String(r.id).padEnd(n))} `+(r.addedByAi?`${o.padEnd(s)} ${x.muted(`added by AI`)}`:o);i.push(t===`Not used`?x.muted(c):c)})}let d=`Next: ${x.brand(`taskgraph show ${r.id}`)} to read it, or ${x.brand(`taskgraph expand --id=${r.id}`)} to break it down`;return i.push(...F(d,t,` `)),i.join(`
95
+ `)}const Xr=(e,t)=>`${e} ${e===1?t:`${t}s`}`;function Zr(e){return e.length<=1?e.join(``):`${e.slice(0,-1).join(`, `)} and ${e[e.length-1]}`}function Qr(e){let t=[];if(e.tags.length>0){let n=Xr(e.taskCount,`task`);t.push(e.tags.length>1?`${n} in ${e.tags.length} tags`:n)}for(let[n,r]of Object.entries(e.copiedFiles))r>0&&t.push(n);return t}function $r(e){let t=e.droppedModels,n=[];if(t.length===1){let[e]=t;n.push(`the ${e.role} model (${e.provider} ${e.modelId})`)}else t.length>1&&n.push(`the ${Zr(t.map(e=>e.role))} models`);return e.droppedSettings.length>0&&n.push(Xr(e.droppedSettings.length,`provider setting`)),n.length>0?`Skipped ${Zr(n)}`:``}function ei(e){let{result:t,changes:n}=e,r=Qr(t),i=[r.length>0?`${w.green(`✓`)} Imported ${Zr(r)} from ${g}/`:`${w.green(`✓`)} Set up TaskGraph; ${g}/ had nothing to import`],a=Math.max(0,...n.map(e=>e.path.length));for(let e of n)i.push(` ${e.path.padEnd(a)} ${x.muted(e.note)}`);let o=$r(t);o&&i.push(x.muted(o));let s=t.taskCount>0?`taskgraph next`:`taskgraph parse-prd`;return i.push(`${x.muted(`${g}/ is unchanged ·`)} Next: ${x.brand(s)}`),i.join(`
96
+ `)}const W=[`main`,`research`,`fallback`],G={main:{label:`Main`,purpose:`creates and updates tasks`},research:{label:`Research`,purpose:`research and --research runs`},fallback:{label:`Fallback`,purpose:`used if the main model fails`}},ti={opus:`most capable`,sonnet:`balanced`,haiku:`fastest`},ni=e=>e.replace(/`([^`]+)`/g,(e,t)=>x.brand(t));function ri(e){return e.map(e=>ti[e]?`${e} (${ti[e]})`:e).join(`, `)}function ii(e,t){let n=Math.max(...W.map(e=>G[e].label.length)),r=Math.max(4,...W.map(t=>e[t]?.length??0)),i=[x.heading(`Models`)];for(let t of W){let{label:a,purpose:o}=G[t],s=e[t],c=s?x.brand(s.padEnd(r)):x.muted(`none`.padEnd(r));i.push(` ${a.padEnd(n)} ${c} ${x.muted(o)}`)}return i.push(``),t.length>0&&i.push(x.muted(`Choices: ${ri(t)}`)),i.push(x.muted(ni("Change them with `taskgraph models --setup`"))),i.join(`
97
+ `)}const ai=e=>e.from===e.to?`${x.brand(e.to)} ${x.muted(`(unchanged)`)}`:e.from?`${e.from} → ${x.brand(e.to)}`:x.brand(e.to);function oi(e){let t=w.green(`✓`);if(e.length===1){let[n]=e;return`${t} ${G[n.role].label} model ${ai(n)}`}let n=Math.max(...e.map(e=>G[e.role].label.length)),r=e.filter(e=>e.from!==e.to);return[r.length===0?`${t} Models unchanged`:`${t} Updated ${r.length} ${r.length===1?`model`:`models`}`,...e.map(e=>` ${G[e.role].label.padEnd(n)} ${ai(e)}`)].join(`
98
+ `)}function si(e,t){if(!e||e.length===0)return x.muted(`none`);let n=new Map(t.map(e=>[e.id.toString(),e]));return e.map(e=>{let t=n.get(e.toString());return t?`${e}${t.status===`done`?`✓`:t.status===`in-progress`?`►`:`○`}`:w.red(`${e} (not found)`)}).join(`, `)}const K=(e,t)=>`${e} ${e===1?t:`${t}s`}`,ci=(e,t)=>e.length>t?`${e.slice(0,Math.max(1,t-1))}…`:e,li=e=>`${String(e).includes(`.`)?`subtask`:`task`} ${e}`;function ui({taskCount:e,subtaskCount:t,dependencyCount:n}){let r=[K(e,`task`)];return t>0&&r.push(K(t,`subtask`)),r.push(n===0?`no dependencies`:n===1?`1 dependency`:`${n} dependencies`),r.join(`, `)}function di(e){switch(e.type){case`self`:return`depends on itself`;case`missing`:return`depends on ${li(e.dependencyId??`?`)}, which doesn't exist`;case`circular`:return`is part of a dependency loop`}}function fi(e){let t=li(e.dependencyId??`?`);switch(e.type){case`self`:return`removed its dependency on itself`;case`missing`:return`removed ${t}, which doesn't exist`;case`duplicate`:return`removed a duplicate of ${t}`;case`circular`:return`removed ${t} to break a loop`}}function pi(e,t){let n=Math.max(...e.map(e=>String(e.taskId).length)),r=Math.max(10,t-4-n);return e.map(e=>` ${x.brand(String(e.taskId).padEnd(n))} ${ci(e.text,r)}`)}function mi(e){let t=e=>String(e).split(`.`).map(Number);return[...e].sort((e,n)=>{let[r,i]=[t(e.taskId),t(n.taskId)];for(let e=0;e<Math.max(r.length,i.length);e++){let t=(r[e]??-1)-(i[e]??-1);if(t!==0)return t}return 0})}function hi(e){return`${w.green(`✓`)} No dependency problems${x.muted(` · ${ui(e)}`)}`}function gi(e,t=M()){let{issues:n}=e;return n.length===0?hi(e):_i(`${K(n.length,`dependency problem`)}`,n,t)}function _i(e,t,n,r=!1){let i=[`${w.red(`✗`)} ${e}`,...pi(t.map(e=>({taskId:e.taskId,text:di(e)})),n)],a=!r&&t.some(e=>e.type!==`circular`||e.fixable);return i.push(a?x.muted(`Run `)+x.brand(`taskgraph fix-dependencies`)+x.muted(` to remove them`):x.muted(`Break the loop with `)+x.brand(`taskgraph remove-dependency --id=<id> --depends-on=<id>`)),i.join(`
99
+ `)}function vi(e,t=M()){let{fixes:n,remaining:r=[]}=e;if(n.length===0&&r.length===0)return hi(e);let i=[];if(n.length>0&&i.push(`${w.green(`✓`)} Fixed ${K(n.length,`dependency problem`)}`,...pi(mi(n).map(e=>({taskId:e.taskId,text:fi(e)})),t)),r.length>0){let e=n.length>0?`${K(r.length,`problem`)} left`:K(r.length,`dependency problem`);i.push(_i(e,r,t,!0))}return i.join(`
100
+ `)}function yi(e=`TaskGraph`){console.log(k(w.bold(e),{padding:1,margin:{top:1,bottom:1},borderStyle:`round`,borderColor:C,textAlignment:`center`}))}function bi(e,t){let n=j();console.error(k(w.red.bold(`X Error: `)+x.text(e)+(t?`
101
+
102
+ `+x.muted(t):``),{padding:1,borderStyle:`round`,borderColor:`red`,width:n}))}const xi=bi;function Si(e){let t=j();console.log(k(w.green.bold(`√ `)+x.text(e),{padding:1,borderStyle:`round`,borderColor:`green`,width:t}))}function Ci(e){let t=j();console.log(k(w.yellow.bold(`⚠ `)+x.text(e),{padding:1,borderStyle:`round`,borderColor:`yellow`,width:t}))}function wi(e){let t=j();console.log(k(x.brand.bold(`i `)+x.text(e),{padding:1,borderStyle:`round`,borderColor:C,width:t}))}const Ti=[{key:`tag`,header:`Tag`,width:12},{key:`id`,header:`ID`,width:10},{key:`title`,header:`Title`,width:`flex`},{key:`status`,header:`Status`,width:15},{key:`priority`,header:`Priority`,width:10},{key:`dependencies`,header:`Dependencies`,width:14,dropOrder:3},{key:`blocks`,header:`Blocks`,width:10,dropOrder:0},{key:`complexity`,header:`Complexity`,width:12,dropOrder:1}];function Ei(e,t){let{showSubtasks:n=!1,showComplexity:r=!1,showDependencies:i=!0,showBlocks:a=!1,showTag:o=!1}=t||{},s={tag:o,dependencies:i,blocks:a,complexity:r},c=Ti.filter(e=>s[e.key]??!0),l=qe(N(),c),u=e=>l.widths[l.keys.indexOf(e)],d=new Be({head:l.keys.map(e=>x.brand.bold(Ti.find(t=>t.key===e)?.header??e)),style:{head:[],border:[]},colWidths:l.widths,wordWrap:!0}),f=e=>l.keys.map(t=>e[t]??``);e.forEach(e=>{let t=e.blocks?.join(`, `)??``;d.push(f({tag:x.accent(e.tagName||`-`),id:w.cyan(e.id.toString()),title:P(e.title,u(`title`)-3),status:A(e.status,!0),priority:Tn(e.priority),dependencies:!e.dependencies||e.dependencies.length===0?x.muted(`-`):w.cyan(e.dependencies.map(e=>String(e)).join(`, `)),blocks:t?_(e.status)?x.muted(t):w.yellow(t):x.muted(`-`),complexity:typeof e.complexity==`number`?V(e.complexity):x.muted(`N/A`)})),n&&e.subtasks&&e.subtasks.length>0&&e.subtasks.forEach(e=>{d.push(f({tag:x.muted(`-`),id:x.muted(` └─ ${e.id}`),title:x.muted(P(e.title,u(`title`)-6)),status:x.muted(A(e.status,!0)),priority:x.muted(e.priority||`medium`),dependencies:x.muted(e.dependencies&&e.dependencies.length>0?e.dependencies.map(e=>String(e)).join(`, `):`-`),blocks:x.muted(`-`),complexity:x.muted(typeof e.complexity==`number`?V(e.complexity):`--`)}))})});let p=l.hidden.length>0?`
103
+ `+x.muted(`Hidden to fit width: ${l.hidden.map(e=>Ti.find(t=>t.key===e)?.header).join(`, `)}`):``;return d.toString()+p}var Di=/* @__PURE__ */ e({BANNER_GRADIENT:()=>he,BORDER_COLOR:()=>C,BRAND_COLORS:()=>be,HELP_GROUPS:()=>Qn,MODEL_NOTES:()=>ti,MODEL_ROLES:()=>G,MODEL_ROLE_ORDER:()=>W,MUTED_BOX_BORDER:()=>_e,ParsePrdProgress:()=>yn,TABLE_BORDER:()=>ge,brandSpinner:()=>mn,calculateDependencyStatistics:()=>ht,calculateSubtaskStatistics:()=>mt,calculateTaskStatistics:()=>pt,completedTaskCount:()=>hn,complexityLevel:()=>En,createLink:()=>I,createProgressBar:()=>Je,createSpinner:()=>B,createTaskLink:()=>rt,createTaskTable:()=>Ei,createUrlLink:()=>nt,displayAsciiBanner:()=>lt,displayBanner:()=>yi,displayCardBox:()=>dt,displayCodebasePatterns:()=>on,displayDashboards:()=>xt,displayDependencyDashboard:()=>bt,displayError:()=>xi,displayErrorBox:()=>bi,displayExistingInfrastructure:()=>tn,displayHeader:()=>It,displayImplementationApproach:()=>an,displayImplementationDetails:()=>Zt,displayImplementationMetadata:()=>cn,displayInfo:()=>wi,displayInitBanner:()=>ut,displayProjectDashboard:()=>yt,displayRecommendedNextTask:()=>dn,displayRelevantFiles:()=>en,displayScopeBoundaries:()=>nn,displaySkillsAndCategory:()=>sn,displaySubtasks:()=>$t,displaySuccess:()=>Si,displaySuggestedActions:()=>ln,displaySuggestedNextSteps:()=>bn,displaySyncMessage:()=>Cn,displayTaskDetails:()=>un,displayTaskHeader:()=>Yt,displayTaskProperties:()=>Xt,displayTechnicalConstraints:()=>rn,displayTestStrategy:()=>Qt,displayWarning:()=>Ci,displayWatchFooter:()=>Sn,fit:()=>nr,formatAddedSubtasks:()=>Gn,formatChecklist:()=>Ut,formatChecklistUpdate:()=>Wt,formatClaim:()=>Wn,formatClearedSubtasks:()=>jr,formatComplexityReport:()=>Ln,formatComplexityRun:()=>In,formatCost:()=>zn,formatDependenciesWithStatus:()=>si,formatDependencyCheck:()=>gi,formatDependencyFixes:()=>vi,formatDuration:()=>_n,formatElapsed:()=>gn,formatExpandAll:()=>xr,formatHelp:()=>er,formatInitSummary:()=>Zn,formatMarkdown:()=>ar,formatModelChanges:()=>oi,formatModelChoices:()=>ri,formatModelConfiguration:()=>ii,formatNotesAdded:()=>gr,formatNothingToUpdate:()=>vr,formatParsePrdSaved:()=>yr,formatPrimeContext:()=>Tr,formatResearchAnswer:()=>or,formatResearchContext:()=>lr,formatResearchSaveFailed:()=>dr,formatResearchSaved:()=>ur,formatStatusChanges:()=>Hn,formatStatusLine:()=>vt,formatTagCopied:()=>Nt,formatTagCreated:()=>At,formatTagDeleted:()=>Pt,formatTagIndicator:()=>Et,formatTagList:()=>Ft,formatTagRenamed:()=>Mt,formatTagSwitched:()=>jt,formatTaskCreated:()=>Yr,formatTaskDetail:()=>Jr,formatTaskUpdated:()=>hr,formatTasksUpdated:()=>_r,formatUncheckedCriteria:()=>Gt,formatUpstreamImport:()=>ei,formatUsageLine:()=>Bn,getBoxWidth:()=>j,getComplexityWithColor:()=>V,getComplexityWithScore:()=>On,getContentWidth:()=>N,getPriorityBreakdown:()=>gt,getPriorityWithColor:()=>Tn,getStatusWithColor:()=>A,getSuggestedActions:()=>Kt,getTaskDescription:()=>fn,renderBlockerExplanation:()=>et,renderDependencyTree:()=>Tt,shouldShowAsciiBanner:()=>ct,sortTaskIds:()=>sr,supportsLinks:()=>it,terminalSafe:()=>tr,terminalWidth:()=>M,theme:()=>x,truncate:()=>P,visibleLength:()=>rr,wrapLine:()=>F});function q(e){let t=e.tag||`master`;return ae(t,e.projectRoot)?(It({tag:t}),!0):!1}function Oi(){return process.env.DEBUG===`true`||process.env.DEBUG===`1`}const ki=/* @__PURE__ */ new Set([`UNKNOWN_ERROR`,`INTERNAL_ERROR`,`STORAGE_ERROR`]),Ai={TASK_NOT_FOUND:"Run `taskgraph list` to see task IDs",JSON_PARSE_ERROR:`Nothing was changed; fix the file or restore it from version control`};function ji(e,t){let n=e;for(;n?.cause&&typeof n.code==`string`&&ki.has(n.code);)n=n.cause;let r=Li(typeof n?.getUserMessage==`function`?n.getUserMessage():typeof n?.getSanitizedDetails==`function`?n.getSanitizedDetails().message:n?.message??String(n)),i=typeof n?.hint==`string`?n.hint:void 0;return{message:r,hint:t??i??Ii(r,n?.code)}}const Mi=/\bsubtask (\d+)\.\d+ not found\b/i,Ni=/\btask\b(?!\s+file).*\bnot found\b/i,Pi=/^(source |target )?tag\b.*\bnot found\b/i,Fi=/^(source |target )?tag\b.*\balready exists\b/i;function Ii(e,t){if(t&&Ai[t])return Ai[t];if(Pi.test(e)||Fi.test(e))return"Run `taskgraph tags` to see your tags";let n=Mi.exec(e);if(n)return`Run \`taskgraph show ${n[1]}\` to see its subtasks`;if(Ni.test(e))return Ai.TASK_NOT_FOUND}function Li(e){return e.trim().replace(/^(error:\s*)+/i,``).replace(/\.$/,``).replace(/\b(task|subtask) with ID "?([\d.]+)"?/gi,`$1 $2`).replace(/^(source |parent )+task\b/i,`Task`).replace(/\bdoes not exist$/i,`not found`)}function Ri({message:e,hint:t}){let n=`${w.red(`✗`)} ${e}`;if(t){let e=t.split(/`([^`]+)`/).map((e,t)=>t%2==1?x.brand(e):x.muted(e)).join(``);n+=`\n ${e}`}return n}function zi(e,t){let[n=``,...r]=e.trim().split(`
104
+ `),i=n.replace(/^error:\s*/i,``).replace(/^option '(?:-\w, )?(--[\w-]+)[^']*' argument missing$/i,`$1 needs a value`),a=i.charAt(0).toUpperCase()+i.slice(1),o=/\(Did you mean (.+?)\?\)/.exec(r.join(` `))?.[1],s;return/^unknown command/i.test(i)?s=o?`Did you mean \`taskgraph ${o}\`?`:"Run `taskgraph --help` to see all commands":o?s=`Did you mean \`${o}\`?`:t&&(s=`Run \`taskgraph ${t} --help\` to see its options`),Ri({message:Li(a),hint:s})}function J(e,t){console.error(`\n${Ri({message:Li(e),hint:t})}`)}function Y(e,t={}){console.error(`\n${Ri(ji(e,t.hint))}`),(Oi()||t.forceStack)&&e?.stack&&(console.error(x.muted(`
105
+ Stack trace:`)),console.error(x.muted(e.stack))),t.skipExit||process.exit(1)}function X(e){return e?De(e):p()}var Bi=class e extends O{tmCore;lastResult;constructor(e){super(e||`list`),this.description(`List tasks with optional filtering`).alias(`ls`).argument(`[status]`,`Filter by status (e.g., pending, done, in-progress) or "all" to show with subtasks`).option(`-s, --status <status>`,`Filter by status (fallback if not using positional)`).option(`-t, --tag <tag>`,`Filter by tag`).option(`--with-subtasks`,`Include subtasks in the output`).option(`-f, --format <format>`,`Output format (text, json, compact)`,`text`).option(`--json`,`Output in JSON format (shorthand for --format json)`).option(`-c, --compact`,`Output in compact format (shorthand for --format compact)`).option(`--no-header`,`Hide the command header`).option(`--silent`,`Suppress output (useful for programmatic usage)`).option(`-p, --project <path>`,`Project root directory (auto-detected if not provided)`).option(`-w, --watch`,`Watch for changes and update list automatically`).option(`--ready`,`Show only tasks ready to work on (dependencies satisfied)`).option(`--blocking`,`Show only tasks that block other tasks`).option(`--all-tags`,`Show tasks from all tags (combine with --ready for actionable tasks)`).action(async(e,t)=>{let n=e||t?.status,r=t?.withSubtasks||!1;e===`all`&&(n=void 0,r=!0);let i={...t,status:n,withSubtasks:r};await this.executeCommand(i)})}async executeCommand(e){try{if(this.validateOptions(e)||process.exit(1),await this.initializeCore(X(e.project)),e.watch)await this.watchTasks(e);else{let t=e.allTags?await this.getTasksFromAllTags(e):await this.getTasks(e);this.setLastResult(t),e.silent||this.displayResults(t,e)}}catch(e){Y(e)}}async watchTasks(e){if(!this.tmCore)throw Error(`TmCore not initialized`);let t=await this.getTasks(e),n=/* @__PURE__ */ new Date;console.clear(),this.displayResults(t,e),Sn(n);let r;try{r=await this.tmCore.tasks.watch(async r=>{if(r.type===`change`)try{t=await this.getTasks(e),n=/* @__PURE__ */ new Date,console.clear(),this.displayResults(t,e),Cn(n),Sn(n)}catch(e){let t=e instanceof Error?e.message:String(e);console.error(w.yellow(`\nWarning: Failed to refresh tasks: ${t}`))}else r.type===`error`&&r.error&&console.error(w.red(`\n⚠ Watch error: ${r.error.message}`))},{tag:e.tag});let i=()=>{r?.unsubscribe(),process.exit(0)};process.on(`SIGINT`,i),process.on(`SIGTERM`,i),await new Promise(()=>{})}catch(e){throw console.error(w.red(`Watch mode error: ${e.message}`)),e}}validateOptions(e){if(e.format&&!oe.includes(e.format))return console.error(w.red(`Invalid format: ${e.format}`)),console.error(x.muted(`Valid formats: ${oe.join(`, `)}`)),!1;if(e.status){let n=e.status.split(`,`).map(e=>e.trim());for(let e of n)if(e!==`all`&&!t.includes(e))return console.error(w.red(`Invalid status: ${e}`)),console.error(x.muted(`Valid statuses: ${t.join(`, `)}`)),!1}return e.allTags&&e.watch?(console.error(w.red(`--all-tags cannot be used with --watch mode`)),console.error(x.muted(`Use --all-tags without --watch, or --watch without --all-tags`)),!1):!0}async initializeCore(e){this.tmCore||=await v({projectPath:e})}async getTasks(e){if(!this.tmCore)throw Error(`TmCore not initialized`);let t=e.status&&e.status!==`all`?e.status.split(`,`).map(e=>e.trim()):void 0,n=e.ready||e.blocking,r=t&&!n?{status:t}:void 0,i=await this.tmCore.tasks.list({tag:e.tag,filter:r,includeSubtasks:e.withSubtasks}),{blocksMap:a,invalidDependencies:o}=te(i.tasks);this.displayInvalidDependencyWarnings(o);let s=i.tasks.map(e=>({...e,blocks:a.get(String(e.id))||[]}));e.ready&&(s=h(s)),e.blocking&&(s=ie(s)),t&&n&&(s=s.filter(e=>t.includes(e.status)));let c=!e.json&&!e.compact&&(e.format??`text`)===`text`&&!e.ready&&!e.blocking?await this.tmCore.tasks.getNext(e.tag):null;return{...i,tasks:s,filtered:s.length,nextTaskId:c?String(c.id):null}}async getTasksFromAllTags(e){if(!this.tmCore)throw Error(`TmCore not initialized`);let t=await this.tmCore.tasks.getTagsWithStats(),n=[],r=0,i=[];for(let a of t.tags){let t=a.name;try{let i=await this.tmCore.tasks.list({tag:t,includeSubtasks:e.withSubtasks});r+=i.tasks.length;let{blocksMap:a,invalidDependencies:o}=te(i.tasks);this.displayInvalidDependencyWarnings(o,t);let s=i.tasks.map(e=>({...e,blocks:a.get(String(e.id))||[],tagName:t})),c=e.ready?h(s):s;n.push(...c)}catch(e){let n=e instanceof Error?e.message:String(e);i.push({name:t,error:n});continue}}if(i.length>0&&(console.warn(w.yellow(`\nWarning: Could not fetch tasks from ${i.length} tag(s):`)),i.forEach(({name:e,error:t})=>{console.warn(x.muted(` ${e}: ${t}`))})),i.length===t.tags.length&&t.tags.length>0)throw Error(`Failed to fetch tasks from any tag. First error: ${i[0].error}`);let a=n;if(e.blocking&&(a=a.filter(e=>e.blocks.length>0)),e.status&&e.status!==`all`){let t=e.status.split(`,`).map(e=>e.trim());a=a.filter(e=>t.includes(e.status))}return{tasks:a,total:r,filtered:a.length,allTags:!0}}displayInvalidDependencyWarnings(e,t){if(e.length===0)return;let n=t?` (tag: ${t})`:``;console.warn(w.yellow(`\nWarning: ${e.length} invalid dependency reference(s) found${n}:`)),e.slice(0,5).forEach(({taskId:e,depId:t})=>{console.warn(x.muted(` Task ${e} depends on non-existent task ${t}`))}),e.length>5&&console.warn(x.muted(` ...and ${e.length-5} more`))}displayResults(e,t){let n=t.format||`text`;switch(t.json?n=`json`:t.compact&&(n=`compact`),n){case`json`:this.displayJson(e);break;case`compact`:this.displayCompact(e,t);break;default:this.displayText(e,t)}}displayJson(e){console.log(JSON.stringify({tasks:e.tasks,metadata:{total:e.total,filtered:e.filtered,tag:e.allTags?`all`:e.tag,allTags:e.allTags||!1}},null,2))}displayCompact(e,t){let{tasks:n,tag:r,allTags:i}=e;t.noHeader!==!0&&q({tag:i?`all tags`:r||`master`,projectRoot:this.tmCore?.projectPath});for(let e of n){let n=a[e.status],r=i&&`tagName`in e?x.accent(`[${e.tagName}] `):``;if(console.log(`${r}${w.cyan(e.id)} ${n} ${e.title}`),t.withSubtasks&&e.subtasks?.length)for(let t of e.subtasks){let e=a[t.status];console.log(` ${x.muted(String(t.id))} ${e} ${x.muted(t.title)}`)}}}displayText(e,t){let{tasks:n,tag:r,allTags:i}=e;if(t.noHeader!==!0&&q({tag:i?`all tags`:r||`master`,projectRoot:this.tmCore?.projectPath}),n.length===0){Ci(`No tasks found matching the criteria.`);return}let a=pt(n),o=mt(n),s=ht(n),c=gt(n),l=e.nextTaskId?n.find(t=>String(t.id)===e.nextTaskId):void 0,u=t.ready||t.blocking||i;if(u||xt(a,o,c,s,l),console.log(Ei(n,{showSubtasks:t.withSubtasks,showDependencies:!0,showBlocks:!0,showComplexity:!0,showTag:i})),!u){if(l){let e=fn(l);dn({id:l.id,title:l.title,priority:l.priority,status:l.status,dependencies:l.dependencies,description:e,complexity:l.complexity})}bn()}}setLastResult(e){this.lastResult=e}getLastResult(){return this.lastResult}async cleanup(){this.tmCore&&=void 0}static register(t,n){let r=new e(n);return t.addCommand(r),r}},Vi=class e extends O{tmCore;lastResult;requestedId;constructor(e){super(e||`show`),this.description(`Display detailed information about one or more tasks`).argument(`[id]`,`Task ID(s) to show (comma-separated for multiple)`).option(`-i, --id <id>`,`Task ID(s) to show (comma-separated for multiple)`).option(`-s, --status <status>`,`Filter subtasks by status`).option(`-f, --format <format>`,`Output format (text, json)`,`text`).option(`--json`,`Output in JSON format (shorthand for --format json)`).option(`--silent`,`Suppress output (useful for programmatic usage)`).option(`-p, --project <path>`,`Project root directory (auto-detected if not provided)`).action(async(e,t)=>{await this.executeCommand(e,t)})}async executeCommand(e,t){try{this.validateOptions(t)||process.exit(1),await this.initializeCore(X(t.project));let n=e||t.id;n||(J(`Missing task ID`,"Try `taskgraph show 3`"),process.exit(1));let r=n.split(`,`).map(e=>e.trim()).filter(e=>e.length>0),i=[];for(let e of r){let t=ne.safeParse(e);t.success||(J(`"${e}" isn't a task ID`,"Use a number like `3`, or `3.1` for a subtask"),process.exit(1)),i.push(t.data)}let a=i.length>1?await this.getMultipleTasks(i,t):await this.getSingleTask(i[0],t);this.setLastResult(a),t.silent||this.displayResults(a,t)}catch(e){Y(e)}}validateOptions(e){return e.format&&![`text`,`json`].includes(e.format)?(console.error(w.red(`Invalid format: ${e.format}`)),console.error(x.muted(`Valid formats: text, json`)),!1):!0}async initializeCore(e){this.tmCore||=await v({projectPath:e})}async getSingleTask(e,t){if(!this.tmCore)throw Error(`TmCore not initialized`);this.requestedId=e;let n=await this.tmCore.tasks.get(e);return{task:n.task,found:n.task!==null,originalTaskId:n.isSubtask?e:void 0}}async getMultipleTasks(e,t){if(!this.tmCore)throw Error(`TmCore not initialized`);let n=[],r=[];for(let t of e){let e=await this.tmCore.tasks.get(t);e.task?n.push(e.task):r.push(t)}return{tasks:n,notFound:r}}displayResults(e,t){switch(t.json?`json`:t.format||`text`){case`json`:this.displayJson(e),`found`in e&&!e.found&&(process.exitCode=1);break;default:`task`in e?this.displaySingleTask(e,t):this.displayMultipleTasks(e,t)}}displayJson(e){console.log(JSON.stringify(e,null,2))}displaySingleTask(e,t){if(!e.found||!e.task){let t=e.originalTaskId??this.requestedId??``,n=t.includes(`.`)?t.split(`.`)[0]:void 0;J(`${n?`Subtask`:`Task`} ${t} not found`,n?`Run \`taskgraph show ${n}\` to see its subtasks`:"Run `taskgraph list` to see task IDs"),process.exitCode=1}else q({tag:this.tmCore?.config.getActiveTag()||`master`,projectRoot:this.tmCore?.projectPath})&&console.log(),console.log(Jr(e.task,{id:e.originalTaskId,statusFilter:t.status,checklist:this.tmCore?.tasks.getChecklist(e.task,!!e.originalTaskId)}))}displayMultipleTasks(e,t){let n=q({tag:this.tmCore?.config.getActiveTag()||`master`,projectRoot:this.tmCore?.projectPath});if(e.notFound.length>0){let t=n?`
106
+ `:``;console.log(w.yellow(`${t}⚠ Not found: ${e.notFound.join(`, `)}`)),n=!0}e.tasks.length===0?Ci(`No tasks found matching the criteria.`):(console.log(x.brand.bold(`${n?`
107
+ `:``}Tasks:\n`)),console.log(Ei(e.tasks,{showSubtasks:!0,showDependencies:!0})))}setLastResult(e){this.lastResult=e}getLastResult(){return this.lastResult}async cleanup(){this.tmCore&&=void 0}static register(t,n){let r=new e(n);return t.addCommand(r),r}},Hi=class e extends O{tmCore;lastResult;constructor(e){super(e||`next`),this.description(`Find the next available task to work on`).option(`-t, --tag <tag>`,`Filter by tag`).option(`-f, --format <format>`,`Output format (text, json)`,`text`).option(`--claim`,`Start the next task and record who took it, in one locked write`).option(`--silent`,`Suppress output (useful for programmatic usage)`).option(`-p, --project <path>`,`Project root directory (auto-detected if not provided)`).action(async e=>{await this.executeCommand(e)})}async executeCommand(e){let t=!1;try{if(this.validateOptions(e),await this.initializeCore(X(e.project)),e.claim){let t=await this.claimNextTask(e);e.silent||this.displayClaim(t,e);return}let t=await this.getNextTask(e);this.setLastResult(t),e.silent||this.displayResults(t,e)}catch(e){t=!0,Y(e,{skipExit:!0})}finally{await this.cleanup()}t&&process.exit(1)}validateOptions(e){if(e.format&&![`text`,`json`].includes(e.format))throw Error(`Invalid format: ${e.format}. Valid formats are: text, json`)}async initializeCore(e){if(!this.tmCore){let t=T.resolve(e);this.tmCore=await v({projectPath:t})}}async getNextTask(e){if(!this.tmCore)throw Error(`TmCore not initialized`);let t=await this.tmCore.tasks.getNext(e.tag),n=e.tag||this.tmCore.config.getActiveTag(),r=await this.tmCore.tasks.list({tag:e.tag}),i=r&&r.tasks.length>0,a=t?await this.tmCore.tasks.loadChecklist(String(t.id),e.tag):void 0;return{task:t,found:t!==null,tag:n,hasAnyTasks:i,...a&&{checklist:a}}}async claimNextTask(e){if(!this.tmCore)throw Error(`TmCore not initialized`);let t=await this.tmCore.tasks.claimNext({tag:e.tag}),n=e.tag||this.tmCore.config.getActiveTag(),r=t?!0:(await this.tmCore.tasks.list({tag:e.tag})).tasks.length>0;return{claimed:t!==null,task:t?.task??null,claimedBy:t?.claimedBy??null,claimedAt:t?.claimedAt??null,tag:n,hasAnyTasks:r}}displayClaim(e,t){t.format===`json`?console.log(JSON.stringify(e,null,2)):console.log(Wn(e.task&&e.claimedBy?{taskId:String(e.task.id),title:e.task.title,claimedBy:e.claimedBy}:null,{hasAnyTasks:e.hasAnyTasks,width:process.stdout.columns||80}))}displayResults(e,t){switch(t.format||`text`){case`json`:this.displayJson(e);break;default:this.displayText(e)}}displayJson(e){console.log(JSON.stringify(e,null,2))}displayText(e){let t=q({tag:e.tag||`master`,projectRoot:this.tmCore?.projectPath});if(!e.found||!e.task){e.hasAnyTasks?(console.log(w.yellow(`✓ All tasks are either completed, blocked by dependencies, or in progress.`)),console.log(`\n${w.dim(`Tip: Try`)} ${w.cyan(`taskgraph list`)} ${w.dim(`to see all tasks`)}`)):(console.log(k(w.yellow(`No tasks found in this project.`),{padding:1,borderStyle:`round`,borderColor:`yellow`,title:`No tasks available`,titleAlignment:`center`})),console.log(`\n${w.dim(`Tip: Create tasks with`)} ${w.cyan(`taskgraph parse-prd`)} ${w.dim(`or`)} ${w.cyan(`taskgraph add-task`)}`));return}let n=e.task;un(n,{customHeader:`Next Task: #${n.id} - ${n.title}`,headerColor:`green`,spaceAbove:t,showSuggestedActions:!0,checklist:e.checklist})}setLastResult(e){this.lastResult=e}getLastResult(){return this.lastResult}async cleanup(){this.tmCore&&=void 0}static register(t,n){let r=new e(n);return t.addCommand(r),r}},Ui=class e extends O{tmCore;constructor(e){super(e||`graph`),this.description(`Show tasks as a dependency tree`).option(`-i, --id <id>`,`Show only this task and the tasks drawn under it`).option(`-t, --tag <tag>`,`Use a specific tag`).option(`-f, --format <format>`,`Output format (text, json)`,`text`).option(`-p, --project <path>`,`Project root directory (auto-detected if not provided)`).action(async e=>{await this.executeCommand(e)})}async executeCommand(e){let t=!1;try{if(e.format&&![`text`,`json`].includes(e.format))throw Error(`Invalid format: ${e.format}. Valid formats are: text, json`);let t=T.resolve(X(e.project));this.tmCore=await v({projectPath:t});let n=await this.tmCore.tasks.getDependencyTree({tag:e.tag,rootId:e.id}),r=await this.tmCore.tasks.getNext(e.tag),i={...n,tag:e.tag||this.tmCore.config.getActiveTag(),nextId:r?String(r.id):null};e.format===`json`?console.log(JSON.stringify(i,null,2)):this.displayText(i)}catch(e){t=!0,Y(e,{skipExit:!0})}finally{this.tmCore=void 0}t&&process.exit(1)}displayText(e){let t=q({tag:e.tag,projectRoot:this.tmCore?.projectPath});if(e.total===0){console.log(w.yellow(`No tasks yet.`)),console.log(`${x.muted(`Create some with`)} ${x.brand(`taskgraph parse-prd`)} ${x.muted(`or`)} ${x.brand(`taskgraph add-task`)}`);return}t&&console.log();let n=Tt(e,{nextId:e.nextId,width:N()});console.log(n.join(`
108
+ `))}static register(t,n){let r=new e(n);return t.addCommand(r),r}},Wi=class e extends O{tmCore;constructor(e){super(e||`why`),this.description(`Explain why a task is blocked`).argument(`[id]`,`Task ID, or a subtask ID like 3.1`).option(`-i, --id <id>`,`Task ID, or a subtask ID like 3.1`).option(`-t, --tag <tag>`,`Use a specific tag`).option(`-f, --format <format>`,`Output format (text, json)`,`text`).option(`-p, --project <path>`,`Project root directory (auto-detected if not provided)`).action(async(e,t)=>{await this.executeCommand(e,t)})}async executeCommand(e,t){let n=!1;try{if(t.format&&![`text`,`json`].includes(t.format))throw Error(`Invalid format: ${t.format}. Valid formats are: text, json`);let n=e||t.id;n||(J(`Missing task ID`,"Try `taskgraph why 3`"),process.exit(1));let r=ne.safeParse(n.trim());r.success||(J(`"${n}" isn't a task ID`,"Use a number like `3`, or `3.1` for a subtask"),process.exit(1));let i=T.resolve(X(t.project));this.tmCore=await v({projectPath:i});let a={...await this.tmCore.tasks.explainBlockers(r.data,{tag:t.tag}),tag:t.tag||this.tmCore.config.getActiveTag()};t.format===`json`?console.log(JSON.stringify(a,null,2)):this.displayText(a)}catch(e){n=!0,Y(e,{skipExit:!0})}finally{this.tmCore=void 0}n&&process.exit(1)}displayText(e){q({tag:e.tag,projectRoot:this.tmCore?.projectPath})&&console.log(),console.log(et(e,{width:N()}).join(`
109
+ `))}static register(t,n){let r=new e(n);return t.addCommand(r),r}},Gi=class e extends O{tmCore;constructor(e){super(e||`prime`),this.description(`Print task context and workflow rules for a coding agent`).option(`-t, --tag <tag>`,`Use a specific tag`).option(`--json`,`Output JSON`).option(`-p, --project <path>`,`Project root directory (auto-detected if not provided)`).action(async e=>{await this.executeCommand(e)})}async executeCommand(e){let t=T.resolve(X(e.project)),n=!1;try{this.tmCore=await v({projectPath:t});let n=await this.tmCore.tasks.getPrimeContext({tag:e.tag});console.log(e.json?JSON.stringify(n,null,2):Tr(n))}catch(e){n=!0,Y(e,{skipExit:!0})}finally{this.tmCore=void 0}n&&process.exit(1)}static register(t,n){let r=new e(n);return t.addCommand(r),r}},Ki=class e extends O{tmCore;lastResult;constructor(e){super(e||`start`),this.description(`Start working on a task by launching claude-code with context`).argument(`[id]`,`Task ID to start working on`).option(`-i, --id <id>`,`Task ID to start working on`).option(`-f, --format <format>`,`Output format (text, json)`,`text`).option(`-p, --project <path>`,`Project root directory (auto-detected if not provided)`).option(`--dry-run`,`Show what would be executed without launching claude-code`).option(`--force`,`Force start even if another task is already in-progress`).option(`--no-status-update`,`Do not automatically update task status to in-progress`).action(async(e,t)=>{await this.executeCommand(e,t)})}async executeCommand(e,t){let n=null;try{this.validateOptions(t)||process.exit(1),n=B(`Initializing TaskGraph...`).start(),await this.initializeCore(X(t.project)),n.succeed(`TaskGraph initialized`);let r=e||t.id||null;r||(n=B(`Finding next available task...`).start(),r=await this.performGetNextTask(),r?n.succeed(`Found next task: #${r}`):n.fail(`No available tasks found`)),r||(xi(`No task ID provided and no available tasks found`),process.exit(1)),t.dryRun||await this.showPreLaunchMessage(r),n=B(`Preparing task execution...`).start();let i=await this.performStartTask(r,t);i.started?n.succeed(t.dryRun?`Dry run completed`:`Task prepared - launching Claude...`):n.fail(`Task execution failed`),!t.dryRun&&i.command&&(n&&!n.isSpinning&&console.log(),await this.executeChildProcess(i.command));let a=i;if(this.setLastResult(a),t.dryRun||!i.started){let e=t.dryRun&&a.task?await this.tmCore?.tasks.loadChecklist(a.subtaskId?`${a.task.id}.${a.subtaskId}`:String(a.task.id)):void 0;this.displayResults(a,t,e)}}catch(e){n&&n.fail(`Operation failed`),Y(e)}}validateOptions(e){return e.format&&![`text`,`json`].includes(e.format)?(console.error(w.red(`Invalid format: ${e.format}`)),console.error(x.muted(`Valid formats: text, json`)),!1):!0}async initializeCore(e){this.tmCore||=await v({projectPath:e})}async performGetNextTask(){if(!this.tmCore)throw Error(`TmCore not initialized`);return this.tmCore.tasks.getNextAvailable()}async showPreLaunchMessage(e){if(!this.tmCore)return;let{task:t,isSubtask:n}=await this.tmCore.tasks.get(e);if(t){let r=n?`Subtask #${e} - ${t.title}`:`Task #${t.id} - ${t.title}`;console.log(w.green(`Starting: `)+w.bold(r)),console.log(x.muted(`Launching Claude Code...`)),console.log()}}async performStartTask(e,t){if(!this.tmCore)throw Error(`TmCore not initialized`);let n=null;!t.noStatusUpdate&&!t.dryRun&&(n=B(`Updating task status to in-progress...`).start());let r=await this.tmCore.tasks.start(e,{dryRun:t.dryRun,force:t.force,updateStatus:!t.noStatusUpdate});if(n&&(r.started?n.succeed(`Task status updated`):n.warn(`Task status update skipped`)),!r)throw Error(`Failed to start task - core result is undefined`);return r}async executeChildProcess(e){return new Promise((t,n)=>{console.log(w.green(`Launching Claude Code…`)),console.log();let r=Ae(e.executable,e.args,{cwd:e.cwd,stdio:`inherit`,shell:!1});r.on(`close`,e=>{e===0?t():n(/* @__PURE__ */ Error(`Process exited with code ${e}`))}),r.on(`error`,e=>{n(/* @__PURE__ */ Error(`Failed to spawn process: ${e.message}`))});let i=()=>{r&&!r.killed&&r.kill(`SIGTERM`)};process.on(`SIGINT`,i),process.on(`SIGTERM`,i),process.on(`exit`,i)})}displayResults(e,t,n){switch(t.format||`text`){case`json`:this.displayJson(e);break;default:this.displayTextResult(e,t,n)}}displayJson(e){console.log(JSON.stringify(e,null,2))}displayTextResult(e,t,n){if(!e.found||!e.task){console.log(k(w.yellow(`Task not found!`),{padding:{top:0,bottom:0,left:1,right:1},borderColor:`yellow`,borderStyle:`round`,margin:{top:1}}));return}let r=e.task;if(t.dryRun){let t=`Dry Run: Starting Task #${r.id} - ${r.title}`;e.subtask&&e.subtaskId&&(t=`Dry Run: Starting Subtask #${r.id}.${e.subtaskId} - ${e.subtask.title}`),un(r,{customHeader:t,headerColor:`yellow`,checklist:n}),e.executionOutput&&(console.log(),console.log(k(w.bold(`Claude-Code Prompt:`)+`
110
+
111
+ `+e.executionOutput,{padding:1,borderStyle:`round`,borderColor:C,width:N()}))),console.log(),console.log(k(w.yellow(`Dry run - claude-code would be launched with the above prompt`),{padding:{top:0,bottom:0,left:1,right:1},borderColor:`yellow`,borderStyle:`round`}))}else if(e.started){let t=`Task: #${r.id} - ${r.title}`,n=r.id;e.subtask&&e.subtaskId&&(t=`Subtask: #${r.id}.${e.subtaskId} - ${e.subtask.title}`,n=`${r.id}.${e.subtaskId}`),console.log(k(w.green.bold(`✓ Task session complete`)+`
112
+
113
+ `+x.text(t)+`
114
+
115
+ `+w.cyan(`Next steps:`)+`
116
+ • Run ${w.yellow(`taskgraph show `+r.id)} to review task details\n• Run ${w.yellow(`taskgraph set-status --id=`+n+` --status=done`)} when complete\n• Run ${w.yellow(`taskgraph next`)} to find the next available task\n• Run ${w.yellow(`taskgraph start`)} to begin the next task`,{padding:1,borderStyle:`round`,borderColor:`green`,width:N(),margin:{top:1}}))}else console.log(k(w.red(`✗ Failed to launch claude-code`+(e.error?`\nError: ${e.error}`:``)),{padding:{top:0,bottom:0,left:1,right:1},borderColor:`red`,borderStyle:`round`}))}setLastResult(e){this.lastResult=e}getLastResult(){return this.lastResult}async cleanup(){this.tmCore&&=void 0}static register(t,n){let r=new e(n);return t.addCommand(r),r}};const qi=[`pending`,`in-progress`,`done`,`deferred`,`cancelled`,`blocked`,`review`],Ji=(e,t=[])=>[...t,e];var Yi=class e extends O{tmCore;lastResult;constructor(e){super(e||`set-status`),this.description(`Update the status of one or more tasks`).alias(`status`).argument(`[id]`,`Task ID(s) - comma-separated for multiple (e.g., 1 or 1,1.1,2)`).argument(`[status]`,`Status - ${qi.join(`, `)}`).option(`-i, --id <id>`,`Task ID(s) (fallback if not using positional)`).option(`-s, --status <status>`,`Status (fallback if not using positional)`).option(`--check <numbers>`,`Check off criteria by number, e.g. 2 or 2,4 (see show)`,Ji).option(`--uncheck <numbers>`,`Clear checked criteria by number`,Ji).option(`--force`,`Mark done even with unchecked criteria`).option(`-f, --format <format>`,`Output format (text, json)`,`text`).option(`--silent`,`Suppress output (useful for programmatic usage)`).option(`-p, --project <path>`,`Project root directory (auto-detected if not provided)`).action(async(e,t,n)=>{let r={...n,id:e||n?.id,status:t||n?.status};await this.executeCommand(r)})}async executeCommand(e){let t=!1;try{e.id||(J(`Missing task ID`,"Try `taskgraph set-status --id=3 --status=done`"),process.exit(1));let n=!!(e.check||e.uncheck),r=[],i=[];if(n){try{r=f(e.check??[]),i=f(e.uncheck??[])}catch(t){J(t.message,`Use the numbers \`taskgraph show ${e.id}\` lists, e.g. --check 1,2`),process.exit(1)}e.id.includes(`,`)&&(J(`--check and --uncheck take one task ID`,`Try \`taskgraph set-status ${e.id.split(`,`)[0].trim()} --check 1\``),process.exit(1))}!e.status&&!n&&(J(`Missing status`,`Try \`taskgraph set-status --id=${e.id} --status=done\``),process.exit(1)),e.status&&!qi.includes(e.status)&&(J(`"${e.status}" isn't a status`,`Use one of: ${qi.join(`, `)}`),process.exit(1)),this.tmCore=await v({projectPath:X(e.project)});let a=e.id.split(`,`).map(e=>e.trim()),o=[];for(let e of a){let t=ne.safeParse(e);t.success||(J(`"${e}" isn't a task ID`,"Use a number like `3`, or `3.1` for a subtask"),process.exit(1)),o.push(t.data)}let s;if(n)try{s={taskId:o[0],...await this.tmCore.tasks.updateChecklist(o[0],{check:r,uncheck:i})}}catch(t){e.format===`json`?console.log(JSON.stringify({success:!1,error:t?.getUserMessage?.()??t?.message,taskId:o[0]})):e.silent||Y(t,{skipExit:!0,hint:`Run \`taskgraph show ${o[0]}\` to see its criteria`}),process.exit(1)}let c=[],u;for(let n of e.status?o:[])try{let t=await this.tmCore.tasks.updateStatus(n,e.status,void 0,{force:e.force});c.push({taskId:t.taskId,oldStatus:t.oldStatus,newStatus:t.newStatus})}catch(r){if(t=!0,e.format===`json`){let e=r?.getSanitizedDetails?r.getSanitizedDetails().message:r instanceof Error?r.message:String(r),t=l(r);console.log(JSON.stringify({success:!1,error:e,taskId:n,...t&&{unchecked:t.unchecked},...s&&{checklist:s},timestamp:(/* @__PURE__ */ new Date()).toISOString()}))}else u=r;break}if(this.lastResult={success:!t,updatedTasks:c,...s&&{checklist:s}},((c.length>0||s!==void 0)&&!(t&&e.format===`json`)||!t)&&this.displayResults(this.lastResult,e),u!==void 0&&!e.silent){let e=l(u);e?console.error(`\n${Gt(u.message,e.taskId,e.unchecked)}`):Y(u,{skipExit:!0})}}catch(n){if(t=!0,e.format===`json`){let e=n instanceof Error?n.message:`Unknown error occurred`;console.log(JSON.stringify({success:!1,error:e}))}else e.silent||Y(n,{skipExit:!0})}finally{this.tmCore}t&&process.exit(1)}displayResults(e,t){switch(t.format||`text`){case`json`:console.log(JSON.stringify(e,null,2));break;default:t.silent||this.displayTextResults(e)}}displayTextResults(e){let t=[],n=e.updatedTasks.some(e=>e.newStatus===`done`);e.checklist&&!n&&t.push(Wt(e.checklist.taskId,e.checklist)),e.updatedTasks.length>0&&t.push(Hn(e.updatedTasks)),t.length>0&&console.log(t.join(`
117
+ `))}getLastResult(){return this.lastResult}static register(t,n){let r=new e(n);return t.addCommand(r),r}};const Z=`taskgraph-ai`,Xi=`stephennmiller/taskgraph-ai`;function Zi(e,t,n){let r=`${x.brand.bold(`Update Available!`)} ${w.dim(e)} → ${w.green(t)}`;if(n&&n.length>0){r+=`
118
+
119
+ `+w.bold(`What's New:`);for(let e of n)r+=`
120
+ `+w.cyan(`• `)+e;r+=`
121
+
122
+ Auto-updating to the latest version...`}else r+=`
123
+
124
+ Auto-updating to the latest version with new features and bug fixes...`;let i=k(r,{padding:1,margin:{top:1,bottom:1},borderColor:`yellow`,borderStyle:`round`});console.log(i)}async function Qi(e){let t=B(x.brand(`Updating ${Z} to version ${w.green(e)}`)).start();return new Promise(n=>{let r=Ae(`npm`,[`install`,`-g`,`${Z}@${e}`,`--no-fund`,`--no-audit`,`--loglevel=warn`],{stdio:[`ignore`,`pipe`,`pipe`]}),i=``;r.stdout.on(`data`,()=>{t.text=x.brand(`Installing ${Z}@${e}...`)}),r.stderr.on(`data`,e=>{i+=e.toString()}),r.on(`close`,r=>{r===0?(t.succeed(w.green(`Successfully updated to version ${w.bold(e)}`)),n(!0)):(t.fail(w.red(`Auto-update failed`)),console.log(w.cyan(`Please run manually: npm install -g ${Z}@${e}`)),i&&console.log(w.dim(`Error: ${i.trim()}`)),n(!1))}),r.on(`error`,r=>{t.fail(w.red(`Auto-update failed`)),console.log(w.red(`Error:`),r.message),console.log(w.cyan(`Please run manually: npm install -g ${Z}@${e}`)),n(!1)})})}async function $i(e){if(process.env.TASKGRAPH_SKIP_AUTO_UPDATE===`1`||process.env.CI||process.env.NODE_ENV===`test`){let e=process.env.TASKGRAPH_SKIP_AUTO_UPDATE===`1`?`TASKGRAPH_SKIP_AUTO_UPDATE=1`:process.env.CI?`CI environment`:`NODE_ENV=test`;return console.log(w.dim(`Skipping auto-update (${e})`)),!1}return Qi(e)}function ea(e){let t=e.slice(2);console.log(w.dim(`Restarting with updated version...
125
+ `));let n=Ae(`taskgraph`,t,{stdio:`inherit`,detached:!1,shell:He.platform===`win32`});n.on(`exit`,(e,t)=>{t?He.kill(He.pid,t):He.exit(e??0)}),n.on(`error`,e=>{console.error(w.red(`Failed to restart with new version:`),e.message),console.log(w.yellow(`Please run your command again manually.`)),He.exit(1)})}function ta(e,t=null){let n=d(e);if(!n)return null;let r;return r=n.parentId===void 0?e.find(e=>String(e.id)===String(n.id)):{id:n.id,title:n.title,status:n.status,priority:n.priority,dependencies:n.dependencies,parentId:Number(n.parentId)},t&&ce(r,t),r}function na(e){let t=Error(e);return t.hint="Use letters, numbers, - and _, like `feature-auth`",t}function ra(e,t){let n=S(e,t);if(n)return n;if(!D.existsSync(e))return{master:{tasks:[],metadata:{created:(/* @__PURE__ */ new Date()).toISOString(),description:`Tasks for master context`}}};throw Error(`Could not read tasks file at ${e}`)}async function ia(e,t,n={},r={},i=`text`){let{mcpLog:a,projectRoot:o}=r,{copyFromCurrent:s=!1,copyFromTag:c,description:l,defaultDescription:u=`Tag created on ${(/* @__PURE__ */ new Date()).toLocaleDateString()}`}=n,d=a||{info:(...e)=>y(`info`,...e),warn:(...e)=>y(`warn`,...e),error:(...e)=>y(`error`,...e),debug:(...e)=>y(`debug`,...e),success:(...e)=>y(`success`,...e)};try{if(!t||typeof t!=`string`)throw Error(`Tag name is required and must be a string`);if(!/^[a-zA-Z0-9_-]+$/.test(t))throw na(`"${t}" isn't a valid tag name`);if([`master`,`main`,`default`].includes(t.toLowerCase()))throw Error(`"${t}" is a reserved tag name`);d.debug(`Creating new tag: ${t}`);let n=ra(e,o),r;if(n._rawTaggedData)r=n._rawTaggedData;else if(n.tasks&&!n.master)r={master:{tasks:n.tasks,metadata:n.metadata||{created:(/* @__PURE__ */ new Date()).toISOString(),updated:(/* @__PURE__ */ new Date()).toISOString(),description:`Tasks live here by default`}}};else{r={};for(let[e,t]of Object.entries(n))e!==`_rawTaggedData`&&e!==`tag`&&(r[e]=t)}if(r[t])throw Error(`Tag "${t}" already exists`);let a=[];if(s||c){let e=c||b(o);a=de(r,e),c&&a.length===0&&d.warn(`Source tag "${c}" not found or has no tasks`),d.debug(`Copying ${a.length} tasks from tag "${e}"`)}else d.debug(`Creating empty tag (no tasks copied)`);r[t]={tasks:[...a],metadata:{created:(/* @__PURE__ */ new Date()).toISOString(),updated:(/* @__PURE__ */ new Date()).toISOString(),description:l||u}};let f={};for(let[e,t]of Object.entries(r))e!==`_rawTaggedData`&&(f[e]=t);return me(e,f,o),d.debug(`Successfully created tag "${t}"`),i===`json`||i===`text`&&console.log(At({tagName:t,tasksCopied:a.length,sourceTag:s||c?c||b(o):null,description:l})),{tagName:t,created:!0,tasksCopied:a.length,sourceTag:s||c?c||b(o):null,description:l||u}}catch(e){throw a&&d.error(`Error creating tag: ${e.message}`),e}}async function aa(e,t,n={},r={},i=`text`){let{mcpLog:a,projectRoot:o}=r,{yes:s=!1}=n,c=a||{info:(...e)=>y(`info`,...e),warn:(...e)=>y(`warn`,...e),error:(...e)=>y(`error`,...e),debug:(...e)=>y(`debug`,...e),success:(...e)=>y(`success`,...e)};try{if(!t||typeof t!=`string`)throw Error(`Tag name is required and must be a string`);if(t===`master`)throw Error(`Cannot delete the "master" tag`);c.debug(`Deleting tag: ${t}`);let n=S(e,o);if(!n)throw Error(`Could not read tasks file at ${e}`);let r;if(n._rawTaggedData)r=n._rawTaggedData;else if(n.tasks&&!n.master)r={master:{tasks:n.tasks,metadata:n.metadata||{created:(/* @__PURE__ */ new Date()).toISOString(),updated:(/* @__PURE__ */ new Date()).toISOString(),description:`Tasks live here by default`}}};else{r={};for(let[e,t]of Object.entries(n))e!==`_rawTaggedData`&&e!==`tag`&&(r[e]=t)}if(!r[t])throw Error(`Tag "${t}" does not exist`);let a=b(o)===t,l=de(r,t).length;if(!s&&l>0&&i===`text`){let e=`tag ${t} and its ${l===1?`task`:`${l} tasks`}`;if(!(process.stdin.isTTY&&process.stdout.isTTY)){let t=/* @__PURE__ */ Error(`Deleting ${e} needs confirmation`);throw t.hint="Pass `--yes` to delete it without asking",t}let n=!1;try{let t=Ue.createPromptModule({clearPromptOnDone:!0});({proceed:n}=await t([{type:`confirm`,name:`proceed`,message:`Delete ${e}? This can't be undone.`,default:!1}]))}catch(e){if(e?.name!==`ExitPromptError`)throw e;console.log(x.muted(`Cancelled; nothing was deleted`)),process.exit(130)}if(!n)return console.log(x.muted(`Cancelled; nothing was deleted`)),{tagName:t,deleted:!1,cancelled:!0}}return await Ce(e,e=>(delete e[t],e)),a&&(await da(o,`master`),c.debug(`Switched current tag to "master"`)),c.debug(`Successfully deleted tag "${t}"`),i===`json`||i===`text`&&console.log(Pt({tagName:t,tasksDeleted:l,switchedToMaster:a})),{tagName:t,deleted:!0,tasksDeleted:l,wasCurrentTag:a,switchedToMaster:a}}catch(e){throw a&&c.error(`Error deleting tag: ${e.message}`),e}}async function oa(e,t,n={}){let r=!1;try{let i;try{let t=D.statSync(e);i=t.birthtime<t.mtime?t.birthtime:t.mtime}catch{i=/* @__PURE__ */ new Date}for(let[e,n]of Object.entries(t))e!==`tasks`&&e!==`tag`&&e!==`_rawTaggedData`&&n&&typeof n==`object`&&Array.isArray(n.tasks)&&(n.metadata||(n.metadata={},r=!0),n.metadata.created||(n.metadata.created=i.toISOString(),r=!0),n.metadata.description||(e===`master`?n.metadata.description=`Tasks live here by default`:n.metadata.description=`Tag created on ${new Date(n.metadata.created).toLocaleDateString()}`,r=!0),n.metadata.updated||(n.metadata.updated=n.metadata.created,r=!0));if(r){let r={};for(let[e,n]of Object.entries(t))e!==`_rawTaggedData`&&(r[e]=n);me(e,r,n.projectRoot)}}catch(e){(n.mcpLog||{warn:(...e)=>y(`warn`,...e)}).warn(`Could not enhance tag metadata: ${e.message}`)}return r}async function sa(e,t={},n={},r=`text`){let{mcpLog:i,projectRoot:a}=n,{showTaskCounts:o=!0,showMetadata:s=!1,ready:c=!1}=t,l=i||{info:(...e)=>y(`info`,...e),warn:(...e)=>y(`warn`,...e),error:(...e)=>y(`error`,...e),debug:(...e)=>y(`debug`,...e),success:(...e)=>y(`success`,...e)};try{l.debug(`Listing available tags`),l.debug(`Using file storage for tags`);let t=ra(e,a),i=b(a),o=t._rawTaggedData||t;await oa(e,o,n);let u=[];for(let[e,t]of Object.entries(o)){if(e===`tasks`||e===`tag`||e===`_rawTaggedData`||!t||typeof t!=`object`||!Array.isArray(t.tasks))continue;let n=t.tasks||[],r=t.metadata||{},a=n.map(e=>({...e,blocks:[]})),o=h(a);u.push({name:e,isCurrent:e===i,completedTasks:n.filter(e=>_(e.status)).length,readyTasks:o.length,tasks:n||[],created:r.created||`Unknown`,description:r.description||`No description`})}u.sort((e,t)=>e.isCurrent?-1:t.isCurrent?1:e.name.localeCompare(t.name));let d=u;return c&&(d=u.filter(e=>e.readyTasks>0),l.debug(`Filtered to ${d.length} tags with ready tasks`)),l.debug(`Found ${d.length} tags`),r===`json`||r===`text`&&console.log(Ft(d.map(e=>({name:e.name,isCurrent:e.isCurrent,taskCount:e.tasks.length,readyTasks:e.readyTasks,completedTasks:e.completedTasks,created:e.created,description:e.description})),{showMetadata:s,ready:c})),{tags:d,currentTag:i,totalTags:d.length}}catch(e){throw i&&l.error(`Error listing tags: ${e.message}`),e}}async function ca(e,t,n={},r={},i=`text`){let{mcpLog:a,projectRoot:o}=r,s=a||{info:(...e)=>y(`info`,...e),warn:(...e)=>y(`warn`,...e),error:(...e)=>y(`error`,...e),debug:(...e)=>y(`debug`,...e),success:(...e)=>y(`success`,...e)};try{if(!t||typeof t!=`string`)throw Error(`Tag name is required and must be a string`);s.debug(`Switching to tag: ${t}`),s.debug(`Using file storage for tag switch`);let n=S(e,o);if(!n)throw Error(`Could not read tasks file at ${e}`);if(!(n._rawTaggedData||n)[t])throw Error(`Tag "${t}" does not exist`);let r=b(o);await da(o,t);let a=S(e,o,t),c=a&&a.tasks||[],l=c.length,u=ta(c);return s.debug(`Successfully switched to tag "${t}"`),i===`json`||i===`text`&&console.log(jt({previousTag:r,currentTag:t,taskCount:l,nextTask:u})),{previousTag:r,currentTag:t,switched:!0,taskCount:l,nextTask:u}}catch(e){throw a&&s.error(`Error switching tag: ${e.message}`),e}}async function la(e,t,n,r={},i={},a=`text`){let{mcpLog:o,projectRoot:s}=i,c=o||{info:(...e)=>y(`info`,...e),warn:(...e)=>y(`warn`,...e),error:(...e)=>y(`error`,...e),debug:(...e)=>y(`debug`,...e),success:(...e)=>y(`success`,...e)};try{if(!t||typeof t!=`string`)throw Error(`Old tag name is required and must be a string`);if(!n||typeof n!=`string`)throw Error(`New tag name is required and must be a string`);if(!/^[a-zA-Z0-9_-]+$/.test(n))throw na(`"${n}" isn't a valid tag name`);if(t===`master`)throw Error(`Cannot rename the "master" tag`);if([`master`,`main`,`default`].includes(n.toLowerCase()))throw Error(`"${n}" is a reserved tag name`);c.debug(`Renaming tag from "${t}" to "${n}"`);let r=S(e,s);if(!r)throw Error(`Could not read tasks file at ${e}`);let i=r._rawTaggedData||r;if(!i[t])throw Error(`Tag "${t}" does not exist`);if(i[n])throw Error(`Tag "${n}" already exists`);let o=b(s)===t;i[n]={...i[t]},i[n].metadata&&(i[n].metadata.renamed={from:t,date:(/* @__PURE__ */ new Date()).toISOString()}),delete i[t],o&&(await da(s,n),c.debug(`Updated current tag reference to "${n}"`));let l={};for(let[e,t]of Object.entries(i))e!==`_rawTaggedData`&&(l[e]=t);me(e,l,s);let u=de(i,n).length;return c.debug(`Successfully renamed tag from "${t}" to "${n}"`),a===`json`||a===`text`&&console.log(Mt({oldName:t,newName:n,isCurrentTag:o})),{oldName:t,newName:n,renamed:!0,taskCount:u,wasCurrentTag:o,isCurrentTag:o}}catch(e){throw o&&c.error(`Error renaming tag: ${e.message}`),e}}async function ua(e,t,n,r={},i={},a=`text`){let{mcpLog:o,projectRoot:s}=i,{description:c}=r,l=o||{info:(...e)=>y(`info`,...e),warn:(...e)=>y(`warn`,...e),error:(...e)=>y(`error`,...e),debug:(...e)=>y(`debug`,...e),success:(...e)=>y(`success`,...e)};try{if(!t||typeof t!=`string`)throw Error(`Source tag name is required and must be a string`);if(!n||typeof n!=`string`)throw Error(`Target tag name is required and must be a string`);if(!/^[a-zA-Z0-9_-]+$/.test(n))throw na(`"${n}" isn't a valid tag name`);if([`master`,`main`,`default`].includes(n.toLowerCase()))throw Error(`"${n}" is a reserved tag name`);l.debug(`Copying tag from "${t}" to "${n}"`);let r=S(e,s);if(!r)throw Error(`Could not read tasks file at ${e}`);let i=r._rawTaggedData||r;if(!i[t])throw Error(`Source tag "${t}" does not exist`);if(i[n])throw Error(`Target tag "${n}" already exists`);let o=de(i,t);i[n]={tasks:JSON.parse(JSON.stringify(o)),metadata:{created:(/* @__PURE__ */ new Date()).toISOString(),updated:(/* @__PURE__ */ new Date()).toISOString(),description:c||`Copy of "${t}" created on ${(/* @__PURE__ */ new Date()).toLocaleDateString()}`,copiedFrom:{tag:t,date:(/* @__PURE__ */ new Date()).toISOString()}}};let u={};for(let[e,t]of Object.entries(i))e!==`_rawTaggedData`&&(u[e]=t);return me(e,u,s),l.debug(`Successfully copied tag from "${t}" to "${n}"`),a===`json`||a===`text`&&console.log(Nt({sourceName:t,targetName:n,tasksCopied:o.length})),{sourceName:t,targetName:n,copied:!0,description:c||`Copy of "${t}" created on ${(/* @__PURE__ */ new Date()).toLocaleDateString()}`}}catch(e){throw o&&l.error(`Error copying tag: ${e.message}`),e}}async function da(e,t){try{let n=ke.join(e,`.taskgraph`,`state.json`),r={};if(D.existsSync(n)){let e=D.readFileSync(n,`utf8`);r=JSON.parse(e)}r.currentTag=t,r.lastSwitched=(/* @__PURE__ */ new Date()).toISOString(),r.branchTagMapping||(r.branchTagMapping={}),r.migrationNoticeShown===void 0&&(r.migrationNoticeShown=!1),D.writeFileSync(n,JSON.stringify(r,null,2),`utf8`)}catch(e){y(`warn`,`Could not update current tag in state.json: ${e.message}`)}}async function fa(e,t,n){try{let r=ke.join(e,`.taskgraph`,`state.json`),i={};if(D.existsSync(r)){let e=D.readFileSync(r,`utf8`);i=JSON.parse(e)}i.branchTagMapping||(i.branchTagMapping={}),i.branchTagMapping[t]=n,D.writeFileSync(r,JSON.stringify(i,null,2),`utf8`)}catch(e){y(`warn`,`Could not update branch-tag mapping: ${e.message}`)}}async function pa(e,t,n={},r={},i=`text`){let{mcpLog:a,projectRoot:o}=r,{copyFromCurrent:s,copyFromTag:c,description:l,autoSwitch:u}=n,{sanitizeBranchNameForTag:d,isValidBranchForTag:f}=await import(`./git-utils-CRR3iPaC.js`),p=a||{info:(...e)=>y(`info`,...e),warn:(...e)=>y(`warn`,...e),error:(...e)=>y(`error`,...e),debug:(...e)=>y(`debug`,...e),success:(...e)=>y(`success`,...e)};try{if(!t||typeof t!=`string`)throw Error(`Branch name is required and must be a string`);if(!f(t))throw Error(`Branch "${t}" cannot be converted to a valid tag name`);let n=d(t);p.debug(`Creating tag "${n}" from git branch "${t}"`);let a=await ia(e,n,{copyFromCurrent:s,copyFromTag:c,description:l,defaultDescription:`Tag created from git branch "${t}"`},r,i);return await fa(o,t,n),p.debug(`Updated branch-tag mapping: ${t} -> ${n}`),u&&(await da(o,n),p.debug(`Automatically switched to tag "${n}"`)),i===`json`?{...a,branchName:t,tagName:n,mappingUpdated:!0,autoSwitched:u||!1}:{branchName:t,tagName:n,created:!0,mappingUpdated:!0,autoSwitched:u||!1}}catch(e){throw a&&p.error(`Error creating tag from branch: ${e.message}`),e}}function ma(e,t){return Object.assign(Error(e),{hint:t})}var ha=class e extends O{tmCore;lastResult;throwOnError=!1;constructor(e){super(e||`tags`),this.description(`Manage tags for task organization`).option(`--show-metadata`,`Show additional tag metadata`).option(`--ready`,`Show only tags with ready tasks available`),this.addListCommand(),this.addAddCommand(),this.addUseCommand(),this.addRemoveCommand(),this.addRenameCommand(),this.addCopyCommand(),this.action(async e=>{await this.executeList(e)})}addListCommand(){this.command(`list`).description(`List all tags with statistics (default action)`).option(`--show-metadata`,`Show additional tag metadata`).option(`--ready`,`Show only tags with ready tasks available`).addHelpText(`after`,`
126
+ Examples:
127
+ $ tm tags # List all tags (default)
128
+ $ tm tags list # List all tags (explicit)
129
+ $ tm tags list --show-metadata # List with metadata
130
+ $ tm tags list --ready # Show only tags with parallelizable work
131
+ `).action(async e=>{await this.executeList(e)})}addAddCommand(){this.command(`add`).description(`Create a new tag`).argument(`[name]`,`Name of the tag to create (omit with --from-branch)`).option(`--description <desc>`,`Tag description`).option(`--copy-from <tag>`,`Copy tasks from another tag`).option(`--from-branch`,`Create tag from current git branch name`).addHelpText(`after`,`
132
+ Examples:
133
+ $ tm tags add feature-auth # Create new tag
134
+ $ tm tags add sprint-2 --copy-from sprint-1 # Create with tasks copied
135
+ $ tm tags add --from-branch # Create from current git branch
136
+ `).action(async(e,t)=>{await this.executeAdd(e,t)})}addUseCommand(){this.command(`use`).description(`Switch to a different tag`).argument(`<name>`,`Name or ID of the tag to switch to`).addHelpText(`after`,`
137
+ Examples:
138
+ $ tm tags use feature-auth # Switch by name
139
+ $ tm tags use abc123 # Switch by ID (last 8 chars)
140
+ `).action(async e=>{await this.executeUse(e)})}addRemoveCommand(){this.command(`remove`).description(`Remove a tag`).argument(`<name>`,`Name or ID of the tag to remove`).option(`-y, --yes`,`Skip confirmation prompt`).addHelpText(`after`,`
141
+ Examples:
142
+ $ tm tags remove old-feature # Remove tag with confirmation
143
+ $ tm tags remove old-feature -y # Remove without confirmation
144
+
145
+ Warning: This will delete all tasks in the tag!
146
+ `).action(async(e,t)=>{await this.executeRemove(e,t)})}addRenameCommand(){this.command(`rename`).description(`Rename a tag`).argument(`<oldName>`,`Current tag name`).argument(`<newName>`,`New tag name`).addHelpText(`after`,`
147
+ Examples:
148
+ $ tm tags rename old-name new-name
149
+ `).action(async(e,t)=>{await this.executeRename(e,t)})}addCopyCommand(){this.command(`copy`).description(`Copy a tag with all its tasks`).argument(`<source>`,`Source tag name`).argument(`<target>`,`Target tag name`).option(`--description <desc>`,`Description for the new tag`).addHelpText(`after`,`
150
+ Examples:
151
+ $ taskgraph tags copy sprint-1 sprint-2
152
+ $ taskgraph tags copy sprint-1 sprint-2 --description "Next sprint tasks"
153
+ `).action(async(e,t,n)=>{await this.executeCopy(e,t,n)})}async initTmCore(){this.tmCore||=await v({projectPath:process.cwd()})}async executeList(e){try{await this.initTmCore();let{projectRoot:t,tasksPath:n}=m(),r=await sa(n,{showTaskCounts:!0,showMetadata:e?.showMetadata||!1,ready:e?.ready||!1},{projectRoot:t},`text`);this.setLastResult({success:!0,action:`list`,tags:r.tags,currentTag:r.currentTag,message:`Found ${r.totalTags} tag(s)`})}catch(e){Y(e),this.setLastResult({success:!1,action:`list`,message:e.message}),this.handleError(e instanceof Error?e:Error(e.message||String(e)))}}async executeAdd(e,t){try{if(e&&t?.fromBranch)throw ma(`Give a tag name or --from-branch, not both`,`--from-branch names the tag after the current git branch`);if(!e&&!t?.fromBranch)throw ma(`tags add needs a tag name`,"Example: `taskgraph tags add feature-auth`, or `--from-branch`");await this.initTmCore();let{projectRoot:r,tasksPath:a}=m(),o={description:t?.description,copyFromTag:t?.copyFrom};if(t?.fromBranch){let t="Name the tag instead: `taskgraph tags add <name>`";if(!await i(r))throw ma(`--from-branch needs a git repository, and this isn't one`,t);let s=await n(r);if(!s||s===`HEAD`)throw ma(`Couldn't tell which git branch is checked out`,t);e=(await pa(a,s,o,{projectRoot:r},`text`)).tagName}else await ia(a,e,o,{projectRoot:r},`text`);this.setLastResult({success:!0,action:`add`,message:`Created tag: ${e}`})}catch(e){Y(e),this.setLastResult({success:!1,action:`add`,message:e.message}),this.handleError(e instanceof Error?e:Error(e.message||String(e)))}}async executeUse(e){try{await this.initTmCore();let{projectRoot:t,tasksPath:n}=m(),r=await ca(n,e,{},{projectRoot:t},`text`);this.setLastResult({success:!0,action:`use`,currentTag:r.currentTag,message:`Switched to tag: ${e}`})}catch(e){Y(e),this.setLastResult({success:!1,action:`use`,message:e.message}),this.handleError(e instanceof Error?e:Error(e.message||String(e)))}}async executeRemove(e,t){try{await this.initTmCore();let{projectRoot:n,tasksPath:r}=m(),i=await aa(r,e,{yes:t?.yes||!1},{projectRoot:n},`text`);this.setLastResult({success:!0,action:`remove`,message:i?.cancelled?`Cancelled; tag ${e} was not removed`:`Removed tag: ${e}`})}catch(e){Y(e),this.setLastResult({success:!1,action:`remove`,message:e.message}),this.handleError(e instanceof Error?e:Error(e.message||String(e)))}}async executeRename(e,t){try{await this.initTmCore();let{projectRoot:n,tasksPath:r}=m();await la(r,e,t,{},{projectRoot:n},`text`),this.setLastResult({success:!0,action:`rename`,message:`Renamed tag from "${e}" to "${t}"`})}catch(e){Y(e),this.setLastResult({success:!1,action:`rename`,message:e.message}),this.handleError(e instanceof Error?e:Error(e.message||String(e)))}}async executeCopy(e,t,n){try{await this.initTmCore();let{projectRoot:r,tasksPath:i}=m();await ua(i,e,t,{description:n?.description},{projectRoot:r},`text`),this.setLastResult({success:!0,action:`copy`,message:`Copied tag from "${e}" to "${t}"`})}catch(e){Y(e),this.setLastResult({success:!1,action:`copy`,message:e.message}),this.handleError(e instanceof Error?e:Error(e.message||String(e)))}}setLastResult(e){this.lastResult=e}getLastResult(){return this.lastResult}setThrowOnError(e){return this.throwOnError=e,this}handleError(e){if(this.throwOnError)throw e;process.exit(1)}static register(t,n){let r=new e(n);return t.addCommand(r),r}},ga=class e extends O{tmCore;constructor(e){super(e||`loop`),this.description(`Run Claude Code in a loop, one task per iteration`).option(`-n, --iterations <number>`,`Maximum iterations`).option(`-p, --prompt <preset|path>`,`Preset name (${s.join(`, `)}) or path to custom prompt file`,`default`).option(`--progress-file <path>`,`Path to progress log file`,`.taskgraph/progress.txt`).option(`-t, --tag <tag>`,`Only work on tasks with this tag`).option(`--project <path>`,`Project root directory (auto-detected if not provided)`).option(`--sandbox`,`Run Claude in Docker sandbox mode`).option(`--trust`,`Run Claude without permission prompts in this project, without asking first (for scripts)`).option(`--no-output`,`Exclude full Claude output from iteration results`).option(`-v, --verbose`,`Show Claude's work in real-time`).action(e=>this.execute(e))}async execute(e){let t=e.prompt||`default`,n=e.progressFile||`.taskgraph/progress.txt`;try{let r=T.resolve(X(e.project));this.tmCore=await v({projectPath:r});let i=t==="default"?await this.tmCore.tasks.getCount(`pending`,e.tag):void 0,a=this.tmCore.loop.resolveIterations({userIterations:e.iterations?parseInt(e.iterations,10):void 0,preset:t,pendingTaskCount:i});if(this.validateIterations(String(a)),q({tag:e.tag||this.tmCore.config.getActiveTag(),projectRoot:this.tmCore.projectPath}),e.sandbox&&this.handleSandboxAuth(),!e.sandbox&&!e.trust&&await this.confirmTrust(),console.log(w.cyan(`Starting TaskGraph Loop...`)),console.log(w.dim(`Preset: ${t}`)),console.log(w.dim(`Max iterations: ${a}`)),console.log(w.dim(`Mode: ${e.sandbox?`Docker sandbox`:`Claude CLI`}`)),t==="default"){let t=await this.tmCore.tasks.getNext(e.tag);console.log(t?x.text(`Next task to work on: ${x.text(t.id)} - ${t.title}`):w.yellow(`No pending tasks found`))}console.log();let o={iterations:a,prompt:t,progressFile:n,tag:e.tag,sandbox:e.sandbox,trusted:e.trust,includeOutput:e.output??!0,verbose:e.verbose??!1,callbacks:this.createOutputCallbacks()},s=await this.tmCore.loop.run(o);this.displayResult(s),(s.finalStatus===`error`||s.finalStatus===`blocked`)&&(process.exitCode=1)}catch(e){Y(e,{skipExit:!0}),process.exit(1)}}async confirmTrust(){if(this.tmCore.loop.isTrusted())return;if(!process.stdin.isTTY||!process.stdout.isTTY)throw Error(`loop runs Claude with permission prompts off. Pass --trust to allow that here, or --sandbox to run in Docker.`);let{confirmed:e}=await Ue.prompt([{type:`confirm`,name:`confirmed`,message:`loop runs Claude with permission prompts off: it can read, edit and run anything in this project without asking. Allow that here?`,default:!1}]);if(!e)throw Error(`Not approved. Use --sandbox to run in Docker.`);this.tmCore.loop.trust()}handleSandboxAuth(){console.log(w.dim(`Checking sandbox auth...`));let e=this.tmCore.loop.checkSandboxAuth();if(e.error)throw Error(e.error);if(e.ready){console.log(w.green(`✓ Sandbox ready`));return}console.log(w.yellow(`Sandbox needs authentication. Starting interactive session...`)),console.log(w.dim(`Please complete auth, then Ctrl+C to continue.
154
+ `));let t=this.tmCore.loop.runInteractiveAuth();if(!t.success)throw Error(t.error||`Interactive authentication failed`);console.log(w.green(`✓ Auth complete
155
+ `))}validateIterations(e){let t=Number(e);if(!Number.isInteger(t)||t<1)throw Error(`Invalid iterations: ${e}. Must be a positive integer.`)}createOutputCallbacks(){return{onIterationStart:(e,t)=>{console.log(),console.log(w.cyan(`━━━ Iteration ${e} of ${t} ━━━`))},onText:e=>{console.log(e)},onToolUse:e=>{console.log(w.dim(` → ${e}`))},onError:(e,t)=>{console.error(t===`warning`?w.yellow(`[Loop Warning] ${e}`):w.red(`[Loop Error] ${e}`))},onStderr:(e,t)=>{process.stderr.write(w.dim(`[Iteration ${e}] `)+t)},onOutput:e=>{console.log(e)},onIterationEnd:e=>{let t=e.status===`success`?w.green:e.status===`error`?w.red:w.yellow;console.log(t(` Iteration ${e.iteration} completed: ${e.status}`))}}}displayResult(e){console.log(),console.log(w.bold(`Loop Complete`)),console.log(w.dim(`─`.repeat(40))),console.log(`Total iterations: ${e.totalIterations}`),console.log(`Tasks completed: ${e.tasksCompleted}`),console.log(`Final status: ${this.formatStatus(e.finalStatus)}`),e.errorMessage&&console.log(w.red(`Error: ${e.errorMessage}`))}formatStatus(e){return{all_complete:w.green(`All tasks complete`),max_iterations:w.yellow(`Max iterations reached`),blocked:w.red(`Blocked`),error:w.red(`Error`)}[e]}static register(t,n){let r=new e(n);return t.addCommand(r),r}};function _a(e,t={}){let n=t.home??je.homedir(),r=t.env??process.env,i=t.platform??process.platform;switch(e){case`zsh`:return{script:T.join(n,`.taskgraph-completion.zsh`),rc:T.join(r.ZDOTDIR||n,`.zshrc`)};case`bash`:{let e=T.join(n,`.bash_profile`),t=i===`darwin`&&E.existsSync(e)?e:T.join(n,`.bashrc`);return{script:T.join(n,`.taskgraph-completion.bash`),rc:t}}case`fish`:return{script:T.join(r.XDG_CONFIG_HOME||T.join(n,`.config`),`fish`,`completions`,`taskgraph.fish`)}}}function Q(e,t=je.homedir()){return e===t||e.startsWith(t+T.sep)?`~${e.slice(t.length)}`:e}function va(e,t,n={}){let r=n.home??je.homedir(),i=_a(e,n),a=E.existsSync(i.script);if(E.mkdirSync(T.dirname(i.script),{recursive:!0}),E.writeFileSync(i.script,t),!i.rc)return{...i,replaced:a,rcUpdated:!1};let o=i.script.startsWith(r+T.sep)?`$HOME${i.script.slice(r.length)}`:i.script,s=E.existsSync(i.rc)?E.readFileSync(i.rc,`utf8`):``;if(s.includes(o)||s.includes(i.script))return{...i,replaced:a,rcUpdated:!1};let c=s===``||s.endsWith(`
156
+ `)?``:`
157
+ `;return E.appendFileSync(i.rc,`${c}\n# TaskGraph Tab completion\n[ -f "${o}" ] && source "${o}"\n`),{...i,replaced:a,rcUpdated:!0}}function ya(e){return JSON.stringify(e).replace(/'/g,`\\u0027`).replace(/\\\\/g,`\\u005c`).replace(/`/g,`\\u0060`)}function ba(e){return`var SPEC = ${ya(e)};\n
158
+ var fs = require("fs");
159
+ var path = require("path");
160
+ var args = process.argv.slice(1);
161
+ var shell = args.shift();
162
+ var words = shell === "bash" ? joinEquals(args) : args;
163
+ if (!words.length) words = [""];
164
+
165
+ function joinEquals(ws) {
166
+ var out = [];
167
+ for (var i = 0; i < ws.length; i++) {
168
+ var last = out[out.length - 1];
169
+ if (ws[i] === "=" && last && last.charAt(0) === "-" && last.indexOf("=") < 0) {
170
+ out[out.length - 1] = last + "=" + (i + 1 < ws.length ? ws[++i] : "");
171
+ } else {
172
+ out.push(ws[i]);
173
+ }
174
+ }
175
+ return out;
176
+ }
177
+
178
+ function findOption(cmd, flag) {
179
+ for (var i = 0; i < cmd.options.length; i++) {
180
+ var o = cmd.options[i];
181
+ if (o.long === flag || o.short === flag) return o;
182
+ }
183
+ return null;
184
+ }
185
+
186
+ function findCommand(cmd, name) {
187
+ for (var i = 0; i < cmd.commands.length; i++) {
188
+ var c = cmd.commands[i];
189
+ if (c.name === name || c.aliases.indexOf(name) >= 0) return c;
190
+ }
191
+ return null;
192
+ }
193
+
194
+ function emit(mode, optPrefix, listPrefix, label, items) {
195
+ var lines = ["@" + mode, "@" + optPrefix, "@" + listPrefix, "@" + label];
196
+ for (var i = 0; i < items.length; i++) {
197
+ lines.push(items[i][1] ? items[i][0] + "\\t" + items[i][1] : items[i][0]);
198
+ }
199
+ process.stdout.write(lines.join("\\n") + "\\n");
200
+ process.exit(0);
201
+ }
202
+
203
+ function startsWith(s, p) {
204
+ return s.slice(0, p.length) === p;
205
+ }
206
+
207
+ function findProject(start) {
208
+ var dir = path.resolve(start);
209
+ for (;;) {
210
+ var file = path.join(dir, ".taskgraph", "tasks", "tasks.json");
211
+ if (fs.existsSync(file)) return { dir: dir, file: file };
212
+ var up = path.dirname(dir);
213
+ if (up === dir) return null;
214
+ dir = up;
215
+ }
216
+ }
217
+
218
+ function readProject() {
219
+ var project = findProject(projectDir || process.cwd());
220
+ if (!project) return null;
221
+ var data;
222
+ try {
223
+ data = JSON.parse(fs.readFileSync(project.file, "utf8"));
224
+ } catch (e) {
225
+ return null;
226
+ }
227
+ if (Array.isArray(data.tasks)) return { tags: [], tasks: data.tasks };
228
+ var tags = Object.keys(data).filter(function (k) {
229
+ return data[k] && Array.isArray(data[k].tasks);
230
+ });
231
+ var tag = tagOverride || process.env.TASKGRAPH_TAG;
232
+ if (!tag) {
233
+ try {
234
+ var state = JSON.parse(
235
+ fs.readFileSync(path.join(project.dir, ".taskgraph", "state.json"), "utf8")
236
+ );
237
+ tag = state.currentTag || state.activeTag;
238
+ } catch (e) {}
239
+ }
240
+ if (!data[tag]) tag = tags.indexOf("master") >= 0 ? "master" : tags[0];
241
+ return { tags: tags, tasks: tag ? data[tag].tasks : [] };
242
+ }
243
+
244
+ function taskIds(tasks) {
245
+ var out = [];
246
+ (function walk(list, parent) {
247
+ for (var i = 0; i < (list || []).length; i++) {
248
+ var t = list[i];
249
+ var raw = String(t.id);
250
+ var id = parent && raw.indexOf(".") < 0 ? parent + "." + raw : raw;
251
+ var title = String(t.title || "").split(/\\s+/).join(" ").trim();
252
+ out.push([id, t.status ? title + " (" + t.status + ")" : title]);
253
+ walk(t.subtasks, id);
254
+ }
255
+ })(tasks, "");
256
+ return out;
257
+ }
258
+
259
+ function completeValue(value, text, optPrefix) {
260
+ if (value.kind === "files" || value.kind === "dirs") {
261
+ emit(value.kind, optPrefix, "", value.kind, []);
262
+ }
263
+ var comma = value.kind === "ids" ? text.lastIndexOf(",") : -1;
264
+ var listPrefix = comma < 0 ? "" : text.slice(0, comma + 1);
265
+ var partial = text.slice(comma + 1);
266
+ var taken = listPrefix.split(",");
267
+ var items = [];
268
+ var label = "values";
269
+ if (value.kind === "choices") {
270
+ items = value.choices.map(function (c) { return [c, ""]; });
271
+ } else if (value.kind === "ids" || value.kind === "tags") {
272
+ var project = readProject();
273
+ if (project && value.kind === "ids") {
274
+ items = taskIds(project.tasks);
275
+ label = "task IDs";
276
+ } else if (project) {
277
+ items = project.tags.map(function (t) { return [t, ""]; });
278
+ label = "tags";
279
+ }
280
+ }
281
+ items = items.filter(function (it) {
282
+ return startsWith(it[0], partial) && taken.indexOf(it[0]) < 0;
283
+ });
284
+ emit("values", optPrefix, listPrefix, label, items);
285
+ }
286
+
287
+ function completeOptions(cmd, cur, used) {
288
+ var items = [];
289
+ for (var i = 0; i < cmd.options.length; i++) {
290
+ var o = cmd.options[i];
291
+ if ((used[o.long] || used[o.short]) && !o.variadic) continue;
292
+ if (o.long && startsWith(o.long, cur)) items.push([o.long, o.description]);
293
+ else if (o.short && startsWith(o.short, cur) && cur.slice(0, 2) !== "--") {
294
+ items.push([o.short, o.description]);
295
+ }
296
+ }
297
+ emit("values", "", "", "options", items);
298
+ }
299
+
300
+ var cmd = SPEC;
301
+ var positional = 0;
302
+ var used = {};
303
+ var expecting = null;
304
+ var projectDir = null;
305
+ var tagOverride = null;
306
+ var cur = words[words.length - 1];
307
+ var before = words.slice(0, -1);
308
+
309
+ for (var i = 0; i < before.length; i++) {
310
+ var w = before[i];
311
+ if (w.length > 1 && w.charAt(0) === "-") {
312
+ var eq = w.indexOf("=");
313
+ var flag = eq < 0 ? w : w.slice(0, eq);
314
+ var opt = findOption(cmd, flag);
315
+ used[flag] = true;
316
+ if (!opt || !opt.value) continue;
317
+ var val = eq < 0 ? before[i + 1] : w.slice(eq + 1);
318
+ if (eq < 0 && opt.optional && val !== undefined && val.charAt(0) === "-") continue;
319
+ if (eq < 0 && i + 1 >= before.length) expecting = opt;
320
+ else if (eq < 0) i++;
321
+ if (opt.long === "--project") projectDir = val;
322
+ if (opt.long === "--tag") tagOverride = val;
323
+ continue;
324
+ }
325
+ var sub = positional === 0 ? findCommand(cmd, w) : null;
326
+ if (sub) {
327
+ cmd = sub;
328
+ used = {};
329
+ } else {
330
+ positional++;
331
+ }
332
+ }
333
+
334
+ if (expecting) completeValue(expecting.value, cur, "");
335
+
336
+ if (cur.charAt(0) === "-") {
337
+ var eqAt = cur.indexOf("=");
338
+ if (eqAt > 0) {
339
+ var o = findOption(cmd, cur.slice(0, eqAt));
340
+ if (o && o.value) completeValue(o.value, cur.slice(eqAt + 1), cur.slice(0, eqAt + 1));
341
+ emit("values", "", "", "values", []);
342
+ }
343
+ completeOptions(cmd, cur, used);
344
+ }
345
+
346
+ if (positional === 0 && cmd.commands.length) {
347
+ emit(
348
+ "values", "", "", "commands",
349
+ cmd.commands
350
+ .filter(function (c) { return startsWith(c.name, cur); })
351
+ .map(function (c) { return [c.name, c.description]; })
352
+ .sort(function (a, b) { return a[0] < b[0] ? -1 : 1; })
353
+ );
354
+ }
355
+
356
+ var arg = cmd.args[positional];
357
+ if (!arg && cmd.args.length && cmd.args[cmd.args.length - 1].variadic) {
358
+ arg = cmd.args[cmd.args.length - 1];
359
+ }
360
+ if (arg && arg.value.kind !== "none") completeValue(arg.value, cur, "");
361
+ if (!arg && cur === "") completeOptions(cmd, cur, used);
362
+ emit("values", "", "", "values", []);
363
+ `}const xa=[`bash`,`zsh`,`fish`];function Sa(e){return xa.includes(e)}function Ca(e=process.env.SHELL){let t=(e||``).split(`/`).pop()||``;return Sa(t)?t:void 0}function wa(e){switch(e){case`bash`:return[`taskgraph completion bash > ~/.taskgraph-completion.bash`,`echo 'source ~/.taskgraph-completion.bash' >> ~/.bashrc`];case`zsh`:return[`taskgraph completion zsh > ~/.taskgraph-completion.zsh`,`echo 'source ~/.taskgraph-completion.zsh' >> ~/.zshrc`];case`fish`:return[`mkdir -p ~/.config/fish/completions`,`taskgraph completion fish > ~/.config/fish/completions/taskgraph.fish`]}}function Ta(e,t){return[`# TaskGraph completion for ${e} (taskgraph ${t})`,`# Install or update with: taskgraph completion --install`,`# Run that again after upgrading TaskGraph.`].join(`
364
+ `)}function Ea(e){return`__taskgraph_program='${e}'
365
+
366
+ _taskgraph() {
367
+ local cur="\${COMP_WORDS[COMP_CWORD]}" line i
368
+ local -a out=()
369
+ while IFS= read -r line; do
370
+ out+=("$line")
371
+ done < <(node -e "$__taskgraph_program" -- bash "\${COMP_WORDS[@]:1:COMP_CWORD}" 2>/dev/null)
372
+ COMPREPLY=()
373
+ [[ \${#out[@]} -ge 4 ]] || return 0
374
+ local mode="\${out[0]#@}" listp="\${out[2]#@}"
375
+ [[ "$cur" == "=" ]] && cur=""
376
+ case "$mode" in
377
+ files)
378
+ compopt -o filenames 2>/dev/null
379
+ while IFS= read -r line; do COMPREPLY+=("$line"); done < <(compgen -f -- "$cur")
380
+ ;;
381
+ dirs)
382
+ compopt -o filenames 2>/dev/null
383
+ while IFS= read -r line; do COMPREPLY+=("$line"); done < <(compgen -d -- "$cur")
384
+ ;;
385
+ *)
386
+ compopt -o nosort 2>/dev/null
387
+ for ((i = 4; i < \${#out[@]}; i++)); do
388
+ COMPREPLY+=("$listp\${out[i]%%$'\\t'*}")
389
+ done
390
+ ;;
391
+ esac
392
+ }
393
+
394
+ complete -F _taskgraph taskgraph
395
+ if alias tm >/dev/null 2>&1; then
396
+ complete -F _taskgraph tm
397
+ fi
398
+ `}function Da(e){return`__taskgraph_program='${e}'
399
+
400
+ _taskgraph() {
401
+ local -a out items
402
+ local mode optp listp label line
403
+ out=("\${(@f)$(node -e "$__taskgraph_program" -- zsh "\${(@)words[2,CURRENT]}" 2>/dev/null)}")
404
+ (( \${#out} >= 4 )) || return 1
405
+ mode=\${out[1]#@} optp=\${out[2]#@} listp=\${out[3]#@} label=\${out[4]#@}
406
+ if [[ -n "$optp$listp" ]]; then
407
+ IPREFIX="$IPREFIX$optp$listp"
408
+ PREFIX="\${PREFIX#"$optp$listp"}"
409
+ fi
410
+ case $mode in
411
+ files) _files ;;
412
+ dirs) _files -/ ;;
413
+ *)
414
+ for line in "\${(@)out[5,-1]}"; do
415
+ [[ -n "$line" ]] || continue
416
+ if [[ "$line" == *$'\\t'* ]]; then
417
+ items+=("\${\${line%%$'\\t'*}//:/\\\\:}:\${line#*$'\\t'}")
418
+ else
419
+ items+=("\${line//:/\\\\:}")
420
+ fi
421
+ done
422
+ (( \${#items} )) || return 1
423
+ _describe -V -t "\${label// /-}" "$label" items
424
+ ;;
425
+ esac
426
+ }
427
+
428
+ if [[ "\${zsh_eval_context[-1]}" == loadautofunc ]]; then
429
+ _taskgraph "$@"
430
+ else
431
+ (( $+functions[compdef] )) || { autoload -Uz compinit && compinit }
432
+ compdef _taskgraph taskgraph
433
+ fi
434
+ `}function Oa(e){return`set -g __taskgraph_program '${e}'
435
+
436
+ function __taskgraph_complete
437
+ set -l tokens (commandline -opc)
438
+ set -e tokens[1]
439
+ set -l cur (commandline -ct)
440
+ set -l out (node -e $__taskgraph_program -- fish $tokens "$cur" 2>/dev/null)
441
+ test (count $out) -ge 4; or return
442
+ set -l mode (string sub -s 2 -- $out[1])
443
+ set -l optp (string sub -s 2 -- $out[2])
444
+ set -l listp (string sub -s 2 -- $out[3])
445
+ set -l value (string sub -s (math (string length -- "$optp") + 1) -- "$cur")
446
+ switch $mode
447
+ case files
448
+ for p in (__fish_complete_path "$value")
449
+ echo "$optp$p"
450
+ end
451
+ case dirs
452
+ for p in (__fish_complete_directories "$value")
453
+ echo "$optp$p"
454
+ end
455
+ case '*'
456
+ test (count $out) -ge 5; or return
457
+ for line in $out[5..-1]
458
+ echo "$optp$listp$line"
459
+ end
460
+ end
461
+ end
462
+
463
+ complete -c taskgraph -f -k -a '(__taskgraph_complete)'
464
+ `}function ka(e,t,n=`unknown`){let r=ba(t);if(r.includes(`'`)||r.includes(`\\\\`))throw Error(`Completion program cannot be quoted for the shell`);let i={bash:Ea,zsh:Da,fish:Oa}[e](r);return`${e===`zsh`?`#compdef taskgraph
465
+ `:``}${Ta(e,n)}\n\n${i}`}const Aa=[`pending`,`in-progress`,`done`,`review`,`blocked`,`deferred`,`cancelled`],ja=[`high`,`medium`,`low`],Ma=/* @__PURE__ */ new Set([`id`,`ids`,`taskid`,`task-id`,`parent`,`dependencies`]),Na=/* @__PURE__ */ new Set([`tag`,`tagname`,`oldname`,`sourcename`,`source`,`name`]),Pa=/* @__PURE__ */ new Set([`--tag`,`--from-tag`,`--to-tag`,`--copy-from`]),Fa=/* @__PURE__ */ new Set([`--from`,`--to`,`--save-to`]),Ia=/* @__PURE__ */ new Set([`file`,`files`,`paths`]),La=/* @__PURE__ */ new Set([`dir`,`path`]),Ra=/* @__PURE__ */ new Set([`add`,`add-tag`]);function za(e){let t=e.match(/[<[]([^>\]]+?)(?:\.\.\.)?[>\]]/);return t?t[1].toLowerCase():void 0}function Ba(e,t,n){if(t?.length)return{kind:`choices`,choices:[...t]};let r=n.long;return r===`--status`||e===`status`?{kind:`choices`,choices:Aa}:r===`--priority`||e===`priority`?{kind:`choices`,choices:ja}:r===`--format`||e===`format`?{kind:`choices`,choices:[`text`,`json`]}:r&&Pa.has(r)?{kind:`tags`}:r&&Fa.has(r)?{kind:`ids`}:r===`--project`||r===`--project-root`||r===`--output`?{kind:r===`--output`?`files`:`dirs`}:e?Ma.has(e)?{kind:`ids`}:Na.has(e)?Ra.has(n.command)?{kind:`none`}:{kind:`tags`}:Ia.has(e)?{kind:`files`}:La.has(e)?{kind:`dirs`}:{kind:`none`}:{kind:`none`}}function Va(e,t){let n=e.required||e.optional;return{short:e.short,long:e.long,description:Ua(e.description),value:n?Ba(za(e.flags),e.argChoices,{long:e.long,command:t}):void 0,...e.optional?{optional:!0}:{},...e.variadic?{variadic:!0}:{}}}function Ha(e,t){return{name:e.name(),variadic:e.variadic,value:Ba(e.name().toLowerCase(),e.argChoices,{command:t})}}function Ua(e){let t=(e||``).split(`
466
+ `)[0].trim().replace(/^(.+?[.!?])\s.*$/,`$1`).replace(/\.$/,``);if(t.length<=60)return t;let n=t.slice(0,59),r=n.lastIndexOf(` `);return`${(r>30?n.slice(0,r):n).replace(/[\s,;:(]+$/,``)}…`}function Wa(e){return!!e._hidden||/^\[deprecated\]/i.test(e.description())}function Ga(e){let t=e=>{let n=e.name(),r=e.options.filter(e=>!e.hidden).map(e=>Va(e,n));return r.some(e=>e.long===`--help`)||r.push({short:`-h`,long:`--help`,description:`Show help`}),{name:n,aliases:e.aliases(),description:Ua(e.description()),options:r,args:e.registeredArguments.map(e=>Ha(e,n)),commands:e.commands.filter(e=>!Wa(e)).map(t)}};return t(e)}var Ka=class e extends O{constructor(e){super(e||`completion`),this.description(`Set up Tab completion for bash, zsh or fish`).addArgument(new Me(`[shell]`,`Shell to complete for (default: yours)`).choices(xa)).option(`--install`,`Install it and load it from your shell startup file`).option(`--script`,`Print the script even when writing to a terminal`).addHelpText(`after`,[``,`Examples:`,` taskgraph completion --install # set it up for your shell`,` taskgraph completion zsh > ~/.taskgraph-completion.zsh`].join(`
467
+ `)).action((e,t)=>{this.executeCommand(e,t)})}executeCommand(e,t){try{let n=e??this.detectedShell();t.install?this.install(n):process.stdout.isTTY&&!t.script?this.displayInstructions(n,!e):process.stdout.write(this.script(n))}catch(e){Y(e,{skipExit:!0}),process.exit(1)}}detectedShell(){let e=Ca();if(!e)throw Error(`Couldn't tell which shell you use. Name it: taskgraph completion <${xa.join(`|`)}>`);return e}script(e){let t=this;for(;t.parent;)t=t.parent;return ka(e,Ga(t),t.version()||`unknown`)}install(e){let t=va(e,this.script(e)),n=w.green(`✓`);console.log(),console.log(`${n} ${t.replaced?`Updated`:`Wrote`} ${x.brand(Q(t.script))}`),t.rc&&t.rcUpdated?console.log(`${n} Loaded it from ${x.brand(Q(t.rc))}`):t.rc&&console.log(`${n} ${x.brand(Q(t.rc))} ${x.muted(`already loads it`)}`),console.log(),console.log(`Open a new terminal, then try ${x.brand(`taskgraph show <Tab>`)}`),console.log(x.muted(`Run this again after upgrading TaskGraph to pick up new commands.`))}displayInstructions(e,t){let n=_a(e),r=n.rc?`Writes ${Q(n.script)} and loads it from ${Q(n.rc)}.`:`Writes ${Q(n.script)}.`;console.log(),console.log(w.bold(`Tab completion for ${e}`)),console.log(),console.log(` ${x.brand(`taskgraph completion --install`)}`),console.log(` ${x.muted(r)}`),console.log(),console.log(x.muted(`Or by hand:`));for(let t of wa(e))console.log(` ${t}`);if(t){let t=xa.filter(t=>t!==e).join(`|`);console.log(),console.log(x.muted(`Not using ${e}? Name your shell: taskgraph completion <${t}> --install`))}}static register(t,n){let r=new e(n);return t.addCommand(r),r}},$=class{useJson;constructor(e){this.useJson=e}output(e){this.useJson?console.log(JSON.stringify(e,null,2)):this.outputText(e)}outputText(e){for(let[t,n]of Object.entries(e))typeof n==`object`&&n?(console.log(w.cyan(`${t}:`)),this.outputObject(n,` `)):console.log(x.text(`${t}: ${n}`))}outputObject(e,t){for(let[n,r]of Object.entries(e))typeof r==`object`&&r?(console.log(w.cyan(`${t}${n}:`)),this.outputObject(r,t+` `)):console.log(x.muted(`${t}${n}: ${r}`))}error(e,t){if(this.useJson)console.error(JSON.stringify({error:e,...t},null,2));else if(console.error(w.red(`Error: ${e}`)),t)for(let[e,n]of Object.entries(t))console.error(x.muted(` ${e}: ${n}`))}success(e,t){this.useJson?console.log(JSON.stringify({success:!0,message:e,...t},null,2)):(console.log(w.green(`✓ ${e}`)),t&&this.output(t))}warning(e){this.useJson?console.warn(JSON.stringify({warning:e},null,2)):console.warn(w.yellow(`⚠ ${e}`))}info(e){this.useJson||console.log(x.brand(`ℹ ${e}`))}},qa=class extends O{constructor(){super(`abort`),this.description(`Abort the current TDD workflow and clean up state`).option(`-f, --force`,`Force abort without confirmation`).action(async e=>{await this.execute(e)})}async execute(e){let t=this.parent?.opts(),n={...t,...e,projectRoot:``},r=new $(e.json||t?.json||!1);try{let i=X(e.projectRoot||t?.projectRoot);n={...n,projectRoot:i};let a=await v({projectPath:i});if(!await a.workflow.hasWorkflow()){r.warning(`No active workflow to abort`);return}await a.workflow.resume();let o=a.workflow.getStatus();if(!n.force&&!n.json){let{confirmed:e}=await Ue.prompt([{type:`confirm`,name:`confirmed`,message:`This will abort the workflow for task ${o.taskId}. Progress: ${o.progress?.completed||0}/${o.progress?.total||0} subtasks completed. Continue?`,default:!1}]);if(!e){r.info(`Abort cancelled`);return}}await a.workflow.abort(),r.success(`Workflow aborted`,{taskId:o.taskId,branchName:o.branchName,progress:o.progress,lastSubtask:o.currentSubtask?{id:o.currentSubtask.id,title:o.currentSubtask.title}:null,note:`Branch and commits remain. Clean up manually if needed.`})}catch(e){r.error(e.message),n.verbose&&console.error(e.stack),process.exit(1)}}},Ja=class extends O{constructor(){super(`commit`),this.description(`Create a commit for the completed GREEN phase`).action(async e=>{await this.execute(e)})}async execute(e){let t=this.parent?.opts(),n={...t,...e,projectRoot:X(e.projectRoot||t?.projectRoot)},i=new $(n.json||!1);try{let e=n.projectRoot,t=await v({projectPath:e});await t.workflow.hasWorkflow()||(i.error(`No active workflow`,{suggestion:`Start a workflow with: autopilot start <taskId>`}),process.exit(1)),await t.workflow.resume();let a=t.workflow.getStatus(),o=t.workflow.getContext();a.tddPhase!==`COMMIT`&&(i.error(`Not in COMMIT phase`,{currentPhase:a.tddPhase||a.phase,suggestion:`Complete RED and GREEN phases first`}),process.exit(1)),a.currentSubtask||(i.error(`No current subtask`),process.exit(1));let s=new r(e);await s.ensureGitRepository(),await s.hasStagedChanges()||(i.info(`No staged changes, staging all changes...`),await s.stageFiles([`.`]));let c=await s.getStatus(),l=[...c.staged,...c.modified],u=new re,d=o.lastTestResults,f=u.generateMessage({type:`feat`,description:a.currentSubtask.title,changedFiles:l,taskId:a.taskId,phase:a.tddPhase,tag:o.metadata.tag||void 0,testsPassing:d?.passed,testsFailing:d?.failed,coveragePercent:void 0});await s.createCommit(f,{metadata:{taskId:a.taskId,subtaskId:a.currentSubtask.id,phase:`COMMIT`,tddCycle:`complete`}});let p=await s.getLastCommit(),m=await t.workflow.commit(),h=m.phase===`COMPLETE`;i.success(`Commit created`,{commitHash:p.hash.substring(0,7),message:f.split(`
468
+ `)[0],subtask:{id:a.currentSubtask.id,title:a.currentSubtask.title},progress:m.progress,nextAction:h?`All subtasks complete. Run: autopilot status`:`Start next subtask with RED phase`})}catch(e){i.error(e.message),n.verbose&&console.error(e.stack),process.exit(1)}}},Ya=class extends O{constructor(){super(`complete`),this.description(`Complete the current TDD phase with result validation`).option(`-r, --results <json>`,`Test results JSON (with total, passed, failed, skipped)`).option(`-c, --coverage <percent>`,`Coverage percentage`).action(async e=>{await this.execute(e)})}async execute(e){let t=this.parent?.opts(),n={...t,...e,projectRoot:X(e.projectRoot||t?.projectRoot)},r=new $(n.json||!1);try{let e=n.projectRoot,t=await v({projectPath:e});await t.workflow.hasWorkflow()||(r.error(`No active workflow`,{suggestion:`Start a workflow with: autopilot start <taskId>`}),process.exit(1)),await t.workflow.resume();let i=t.workflow.getStatus(),a=i.tddPhase,o=i.currentSubtask;if(a||(r.error(`Not in a TDD phase`,{phase:i.phase}),process.exit(1)),a===`RED`||a===`GREEN`){n.results||(r.error(`Test results required for RED/GREEN phase`,{usage:`--results '{"total":10,"passed":9,"failed":1,"skipped":0}'`}),process.exit(1));let e;try{let t=JSON.parse(n.results);e={total:t.total||0,passed:t.passed||0,failed:t.failed||0,skipped:t.skipped||0,phase:a}}catch(e){r.error(`Invalid test results JSON`,{error:e.message}),process.exit(1)}a===`RED`&&e.failed===0&&(r.error(`RED phase validation failed`,{reason:`At least one test must be failing`,actual:{passed:e.passed,failed:e.failed}}),process.exit(1)),a===`GREEN`&&e.failed!==0&&(r.error(`GREEN phase validation failed`,{reason:`All tests must pass`,actual:{passed:e.passed,failed:e.failed}}),process.exit(1));let i=await t.workflow.completePhase(e);a===`RED`?r.success(`RED phase completed`,{nextPhase:i.tddPhase||`GREEN`,testResults:e,subtask:o?.title}):r.success(`GREEN phase completed`,{nextPhase:i.tddPhase||`COMMIT`,testResults:e,subtask:o?.title,suggestion:`Run: autopilot commit`})}else a===`COMMIT`&&(r.error(`Use "autopilot commit" to complete COMMIT phase`),process.exit(1))}catch(e){r.error(e.message),n.verbose&&console.error(e.stack),process.exit(1)}}},Xa=class extends O{constructor(){super(`finalize`),this.description(`Finalize and complete the workflow. Validates working tree is clean.`).action(async e=>{await this.execute(e)})}async execute(e){let t=this.parent?.opts(),n={...t,...e,projectRoot:``},r=new $(e.json||t?.json||!1);try{let i=X(e.projectRoot||t?.projectRoot);n={...n,projectRoot:i};let a=await v({projectPath:i});await a.workflow.hasWorkflow()||(r.error(`No active workflow`,{suggestion:`Start a workflow with: autopilot start <taskId>`}),process.exit(1)),await a.workflow.resume();let o=a.workflow.getStatus();o.phase!==`FINALIZE`&&(r.error(`Cannot finalize: workflow is in ${o.phase} phase`,{suggestion:`Complete all subtasks first`}),process.exit(1)),r.info(`Validating working tree and finalizing workflow...`);let s=await a.workflow.finalize();r.success(`Workflow completed`,{taskId:s.taskId,phase:s.phase,branchName:s.branchName,progress:s.progress})}catch(e){r.error(e.message),n.verbose&&console.error(e.stack),process.exit(1)}}},Za=class extends O{constructor(){super(`next`),this.description(`Get the next action to perform in the TDD workflow`).action(async e=>{await this.execute(e)})}async execute(e){let t=this.parent?.opts(),n={...t,...e,projectRoot:``},r=new $(e.json||t?.json||!1);try{let i=X(e.projectRoot||t?.projectRoot);n={...n,projectRoot:i};let a=await v({projectPath:i});await a.workflow.hasWorkflow()||(r.error(`No active workflow`,{suggestion:`Start a workflow with: autopilot start <taskId>`}),process.exit(1)),await a.workflow.resume();let o=a.workflow.getStatus(),s=a.workflow.getNextAction(),c=a.workflow.getContext(),l=o.phase,u=o.tddPhase,d=o.currentSubtask;if(l===`COMPLETE`){r.success(`Workflow complete`,{message:`All subtasks have been completed`,taskId:o.taskId});return}let f={action:s.action,description:s.description,phase:l,tddPhase:u,taskId:o.taskId,branchName:o.branchName,subtask:d?{id:d.id,title:d.title,attempts:d.attempts}:null,nextSteps:s.nextSteps,lastTestResults:c.lastTestResults};n.json?r.output(f):r.success(`Next action`,f)}catch(e){r.error(e.message),n.verbose&&console.error(e.stack),process.exit(1)}}},Qa=class extends O{constructor(){super(`resume`),this.description(`Resume a previously started TDD workflow`).action(async e=>{await this.execute(e)})}async execute(e){let t=this.parent?.opts(),n={...t,...e,projectRoot:X(e.projectRoot||t?.projectRoot)},r=new $(n.json||!1);try{let e=n.projectRoot,t=await v({projectPath:e});await t.workflow.hasWorkflow()||(r.error(`No workflow state found`,{suggestion:`Start a new workflow with: autopilot start <taskId>`}),process.exit(1)),r.info(`Loading workflow state...`);let i=await t.workflow.resume();r.success(`Workflow resumed`,{taskId:i.taskId,phase:i.phase,tddPhase:i.tddPhase,branchName:i.branchName,progress:i.progress,currentSubtask:i.currentSubtask?{id:i.currentSubtask.id,title:i.currentSubtask.title,attempts:i.currentSubtask.attempts}:null})}catch(e){r.error(e.message),n.verbose&&console.error(e.stack),process.exit(1)}}},$a=class extends O{constructor(){super(`start`),this.description(`Initialize and start a new TDD workflow for a task`).argument(`<taskId>`,`Task ID to start workflow for`).option(`-f, --force`,`Force start even if workflow state exists`).option(`--max-attempts <number>`,`Maximum attempts per subtask`,`3`).action(async(e,t)=>{await this.execute(e,t)})}async execute(e,t){let n=this.parent?.opts(),r={...n,...t,projectRoot:X(t.projectRoot||n?.projectRoot)},i=new $(r.json||!1);try{let t=u.safeParse(e);t.success||(i.error(`Invalid task ID format`,{taskId:e,error:t.error.issues[0]?.message}),process.exit(1));let n=t.data,a=r.projectRoot,o=await v({projectPath:a});await o.workflow.hasWorkflow()&&!r.force&&(i.error(`Workflow state already exists. Use --force to overwrite or resume with "autopilot resume"`),process.exit(1));let s=o.config.getActiveTag();i.info(`Loading task ${n}...`);let{task:c}=await o.tasks.get(n);c||(i.error(`Task not found`,{taskId:n}),process.exit(1)),(!c.subtasks||c.subtasks.length===0)&&(i.error(`Task has no subtasks. Expand task first.`,{taskId:n,suggestion:`Run: taskgraph expand --id=${n}`}),process.exit(1));let l=parseInt(r.maxAttempts||`3`,10);i.info(`Starting TDD workflow...`);let d=await o.workflow.start({taskId:n,taskTitle:c.title,subtasks:c.subtasks.map(e=>({id:e.id,title:e.title,status:e.status,maxAttempts:l})),maxAttempts:l,force:r.force,tag:s});i.success(`TDD workflow started`,{taskId:d.taskId,title:c.title,phase:d.phase,tddPhase:d.tddPhase,branchName:d.branchName,subtasks:c.subtasks.length,currentSubtask:d.currentSubtask?.title})}catch(e){i.error(e.message),r.verbose&&console.error(e.stack),process.exit(1)}}},eo=class extends O{constructor(){super(`status`),this.description(`Show current TDD workflow status and progress`).action(async e=>{await this.execute(e)})}async execute(e){let t=this.parent?.opts(),n={...t,...e,projectRoot:X(e.projectRoot||t?.projectRoot)},r=new $(n.json||!1);try{let e=n.projectRoot,t=await v({projectPath:e});if(!await t.workflow.hasWorkflow()){n.json?r.output({active:!1,message:`No active workflow`}):(r.info(`No active workflow`),console.log(`Start a workflow with: autopilot start <taskId>`));return}await t.workflow.resume();let i=t.workflow.getStatus(),a=t.workflow.getContext(),o={taskId:i.taskId,phase:i.phase,tddPhase:i.tddPhase,branchName:i.branchName,progress:i.progress,currentSubtask:i.currentSubtask?{id:i.currentSubtask.id,title:i.currentSubtask.title,attempts:i.currentSubtask.attempts,maxAttempts:i.currentSubtask.maxAttempts}:null,subtasks:a.subtasks.map(e=>({id:e.id,title:e.title,status:e.status,attempts:e.attempts})),errors:a.errors&&a.errors.length>0?a.errors:void 0,metadata:a.metadata};n.json?r.output(o):r.success(`Workflow status`,o)}catch(e){r.error(e.message),n.verbose&&console.error(e.stack),process.exit(1)}}},to=class e extends O{constructor(){super(`autopilot`),this.description(`AI agent orchestration for TDD workflow execution`).alias(`ap`).option(`--json`,`Output in JSON format for machine parsing`).option(`-v, --verbose`,`Enable verbose output`).option(`-p, --project-root <path>`,`Project root directory (auto-detected if not specified)`),this.registerSubcommands()}registerSubcommands(){this.addCommand(new $a),this.addCommand(new Qa),this.addCommand(new Za),this.addCommand(new Ya),this.addCommand(new Ja),this.addCommand(new eo),this.addCommand(new Xa),this.addCommand(new qa)}static register(t){let n=new e;return t.addCommand(n),n}},no=class e extends O{tmCore;lastResult;constructor(e){super(e||`generate`),this.description(`Generate individual task files from tasks.json`).option(`-t, --tag <tag>`,`Tag context for task operations`).option(`-o, --output <dir>`,`Output directory for generated files (defaults to .taskgraph/tasks)`).option(`-p, --project <path>`,`Project root directory (auto-detected if not provided)`).option(`-f, --format <format>`,`Output format (text, json)`,`text`).action(async e=>{await this.executeCommand(e)})}async executeCommand(e){let t=!1;try{this.validateOptions(e);let t=X(e.project);await this.initializeCore(t);let n=await this.generateFiles(t,e);this.lastResult=n,this.displayResults(n,e)}catch(e){t=!0,Y(e,{skipExit:!0})}finally{await this.cleanup()}t&&process.exit(1)}validateOptions(e){if(e.format&&![`text`,`json`].includes(e.format))throw Error(`Invalid format: ${e.format}. Valid formats are: text, json`)}async initializeCore(e){if(!this.tmCore){let t=T.resolve(e);this.tmCore=await v({projectPath:t})}}async generateFiles(e,t){if(!this.tmCore)throw Error(`TmCore not initialized`);let n=t.output?T.resolve(e,t.output):void 0;return this.tmCore.tasks.generateTaskFiles({tag:t.tag,outputDir:n})}displayResults(e,t){switch(t.format||`text`){case`json`:this.displayJson(e);break;default:this.displayText(e,t)}}displayJson(e){console.log(JSON.stringify(e,null,2))}displayText(e,t){if(this.tmCore&&q({tag:t.tag||this.tmCore.config.getActiveTag(),projectRoot:this.tmCore.projectPath}),!e.success){console.log(k(w.red(`Error: ${e.error||`Unknown error`}`),{padding:1,borderStyle:`round`,borderColor:`red`,title:`Generation failed`,titleAlignment:`center`}));return}if(e.count===0){console.log(k(w.yellow(`No tasks found to generate files for.`),{padding:1,borderStyle:`round`,borderColor:`yellow`,title:`No tasks`,titleAlignment:`center`}));return}let n=`${w.green(`✓`)} Generated ${w.cyan(e.count)} task file(s)`;n+=`\n\n${w.dim(`Output directory:`)} ${e.directory}`,e.orphanedFilesRemoved>0&&(n+=`\n${w.dim(`Orphaned files removed:`)} ${e.orphanedFilesRemoved}`),console.log(k(n,{padding:1,borderStyle:`round`,borderColor:`green`,title:`Task files generated`,titleAlignment:`center`}))}getLastResult(){return this.lastResult}async cleanup(){this.tmCore&&=void 0}static register(t,n){let r=new e(n);return t.addCommand(r),r}};const ro={create:w.green,update:w.yellow,skip:x.muted,close:w.red};function io(e){let t={create:0,update:0,skip:0,close:0};for(let n of e.steps)t[n.action]++;return t}function ao(e){let t=io(e);return t.create+t.update+t.close>0}function oo(e){let t=ro[e.action](e.action.padEnd(6)),n=e.issueNumber?` -> #${e.issueNumber}`:``,r=e.reason?x.muted(` (${e.reason})`):``;return` ${t} [${e.tag}] ${e.taskId} ${e.title}${n}${r}`}function so(e){let t=io(e),n=[w.bold(`Plan for ${e.repo}`),` ${t.create} to create, ${t.update} to update, ${t.skip} unchanged, ${t.close} to close`];for(let t of e.steps.filter(e=>e.action!==`skip`))n.push(oo(t));if(e.orphans.length>0){n.push(``,w.yellow(`${e.orphans.length} open issue(s) have no local task (pass --close-orphans to close them):`));for(let t of e.orphans)n.push(` #${t.issueNumber} ${t.title}`)}return n.join(`
469
+ `)}function co(e){let t=e.dryRun?`would be `:``;return[w.bold(e.dryRun?`Dry run, nothing written`:`Push complete`),` ${t}created ${e.created}, ${t}updated ${e.updated}, unchanged ${e.skipped}, ${t}closed ${e.closed}`].join(`
470
+ `)}const lo={apply:w.green,sync:x.muted,conflict:w.red,skip:x.muted};function uo(e){let t={apply:0,sync:0,conflict:0,skip:0};for(let n of e.steps)t[n.action]++;return t}function fo(e){let t=uo(e);return t.apply+t.sync>0}function po(e){return uo(e).apply>0}function mo(e){let t=lo[e.action](e.action.padEnd(8)),n=e.action===`conflict`?`local ${e.from}, GitHub ${e.to}`:`${e.from} -> ${e.to}`,r=e.issueNumber?` (#${e.issueNumber})`:``;return` ${t} [${e.tag}] ${e.taskId} ${e.title}${r} ${x.muted(n)}`}function ho(e){let t=uo(e),n=[w.bold(`Pull plan for ${e.repo}`),` ${t.apply} to update, ${t.sync} already in sync, ${t.conflict} conflict(s), ${t.skip} unchanged or skipped`];for(let t of e.steps.filter(e=>e.action!==`skip`))n.push(mo(t));return t.conflict>0&&n.push(``,w.yellow(`${t.conflict} task(s) changed on both sides and keep their local status. Run \`taskgraph github push\` to overwrite GitHub with it.`)),n.join(`
471
+ `)}function go(e){let t=e.dryRun?`would be `:``;return[w.bold(e.dryRun?`Dry run, nothing written`:`Pull complete`),` ${t}updated ${e.applied}, ${t}marked in sync ${e.synced}, conflicts ${e.conflicts}, skipped ${e.skipped}`].join(`
472
+ `)}function _o(e){let t=e.ghAvailable?w.green(`available and signed in`):w.red("not available (install gh and run `gh auth login`)");return[w.bold(`GitHub`),` gh CLI: ${t}`,` repo: ${e.repo??x.muted(`not detected (use --repo owner/name)`)}`,` linked: ${e.linkedTasks} task(s)`,` unlinked: ${e.unlinkedTasks} task(s)`].join(`
473
+ `)}function vo(e){return[`Unlinked task ${e.taskId} [${e.tag}] from issue #${e.issueNumber} (${e.url}).`,x.muted(`The issue was not changed. If it still carries its taskgraph marker, the next push will link it again.`)].join(`
474
+ `)}var yo=class extends O{tmCore;constructor(e){super(e||`github`),this.description(`Push tasks to GitHub Issues and pull issue status back`),this.addStatusCommand(),this.addPushCommand(),this.addPullCommand(),this.addUnlinkCommand()}addStatusCommand(){this.command(`status`).description(`Show gh availability, target repo and linked task counts`).option(`--repo <owner/name>`,`Repository to check`).option(`-p, --project <path>`,`Project root directory`).option(`--json`,`Output as JSON`).action(e=>this.guard(e,()=>this.runStatus(e)))}addPushCommand(){this.command(`push`).description(`Create or update GitHub issues for tasks`).option(`--tag <name>`,`Tag to push (default: the active tag)`).option(`--all-tags`,`Push every tag`).option(`--id <ids>`,`Only push these task ids, comma separated`).option(`--dry-run`,`Show the plan without writing anything`).option(`-y, --yes`,`Write without asking for confirmation`).option(`--repo <owner/name>`,`Repository (default: detected via gh)`).option(`--include-details`,`Include task details in issue bodies`).option(`--close-orphans`,`Close open issues whose task is gone`).option(`-p, --project <path>`,`Project root directory`).option(`--json`,`Output as JSON (requires --yes or --dry-run)`).addHelpText(`after`,`
475
+ Examples:
476
+ $ taskgraph github push --dry-run # Preview the active tag
477
+ $ taskgraph github push --all-tags -y # Push every tag without asking
478
+ $ taskgraph github push --id 1,2 # Push only tasks 1 and 2
479
+ `).action(e=>this.guard(e,()=>this.runPush(e)))}addPullCommand(){this.command(`pull`).description(`Update task statuses from their GitHub issues (status only, never writes to GitHub)`).option(`--tag <name>`,`Tag to pull (default: the active tag)`).option(`--all-tags`,`Pull every tag`).option(`--id <ids>`,`Only pull these task ids, comma separated`).option(`--dry-run`,`Show the plan without changing any task`).option(`-y, --yes`,`Update tasks without asking for confirmation`).option(`--repo <owner/name>`,`Repository (default: detected via gh)`).option(`-p, --project <path>`,`Project root directory`).option(`--json`,`Output as JSON (requires --yes or --dry-run)`).addHelpText(`after`,`
480
+ A task that changed on GitHub and not locally takes the issue's status.
481
+ A task that changed on both sides keeps its local status and is reported.
482
+
483
+ Examples:
484
+ $ taskgraph github pull --dry-run # Preview the active tag
485
+ $ taskgraph github pull -y # Update tasks without asking
486
+ `).action(e=>this.guard(e,()=>this.runPull(e)))}addUnlinkCommand(){this.command(`unlink`).description(`Forget the GitHub issue a task is linked to`).argument(`<id>`,`Task id`).option(`--tag <name>`,`Tag the task lives in`).option(`-p, --project <path>`,`Project root directory`).option(`--json`,`Output as JSON`).action((e,t)=>this.guard(t,()=>this.runUnlink(e,t)))}async guard(e,t){let n=!1;try{await this.initializeCore(e),await t()}catch(e){n=!0,Y(e,{skipExit:!0})}finally{await this.tmCore?.close()}n&&process.exit(1)}async initializeCore(e){if(!this.tmCore){let t=T.resolve(X(e.project));this.tmCore=await v({projectPath:t})}}core(){if(!this.tmCore)throw Error(`TmCore not initialized`);return this.tmCore}async runStatus(e){let t=await this.core().github.status({repo:e.repo});console.log(e.json?JSON.stringify(t,null,2):_o(t))}async runPush(e){let t=this.core(),n={repo:e.repo,tag:e.tag,allTags:e.allTags,taskIds:e.id,includeDetails:e.includeDetails,closeOrphans:e.closeOrphans};if(e.dryRun){let r=await t.github.push({...n,dryRun:!0});this.print(e,r,[so(r.plan),co(r)]);return}let r=await t.github.planPush(n);if(!ao(r)){let i=await t.github.push({...n,dryRun:!0});this.print(e,{...i,dryRun:!1},[so(r),`GitHub is already up to date.`]);return}if(!e.yes){if(e.json||!this.isInteractive())throw Error(`Refusing to write to GitHub without confirmation. Pass --yes to proceed or --dry-run to preview.`);if(console.log(so(r)),!await this.confirm(`Write these changes to ${r.repo}?`)){console.log(`Cancelled. Nothing was written.`);return}}let i=await t.github.push({...n,dryRun:!1});this.print(e,i,[...e.yes?[so(i.plan)]:[],co(i)])}async runPull(e){let t=this.core(),n={repo:e.repo,tag:e.tag,allTags:e.allTags,taskIds:e.id};if(e.dryRun){let r=await t.github.pull({...n,dryRun:!0});this.print(e,r,[ho(r.plan),go(r)]);return}let r=await t.github.planPull(n);if(!fo(r)){let i=await t.github.pull({...n,dryRun:!0});this.print(e,{...i,dryRun:!1},[ho(r),`Task statuses are already up to date.`]);return}if(po(r)&&!e.yes){if(e.json||!this.isInteractive())throw Error(`Refusing to change tasks without confirmation. Pass --yes to proceed or --dry-run to preview.`);if(console.log(ho(r)),!await this.confirm(`Update these task statuses?`)){console.log(`Cancelled. Nothing was changed.`);return}}let i=await t.github.pull({...n,dryRun:!1});this.print(e,i,[...e.yes?[ho(i.plan)]:[],go(i)])}async runUnlink(e,t){let n=await this.core().github.unlink(e,{tag:t.tag});console.log(t.json?JSON.stringify(n,null,2):vo(n))}print(e,t,n){console.log(e.json?JSON.stringify(t,null,2):n.join(`
487
+
488
+ `))}isInteractive(){return!!(process.stdin.isTTY&&process.stdout.isTTY)}async confirm(e){let{proceed:t}=await Ue.prompt([{type:`confirm`,name:`proceed`,message:e,default:!1}]);return t}},bo=class{static commands=[{name:`list`,description:`List all tasks with filtering and status overview`,commandClass:Bi,category:`task`},{name:`show`,description:`Display detailed information about a specific task`,commandClass:Vi,category:`task`},{name:`next`,description:`Find the next available task to work on`,commandClass:Hi,category:`task`},{name:`graph`,description:`Show tasks as a dependency tree`,commandClass:Ui,category:`task`},{name:`why`,description:`Explain why a task is blocked`,commandClass:Wi,category:`task`},{name:`start`,description:`Start working on a task with claude-code`,commandClass:Ki,category:`task`},{name:`set-status`,description:`Update the status of one or more tasks`,commandClass:Yi,category:`task`},{name:`autopilot`,description:`AI agent orchestration for TDD workflow (start, resume, next, complete, commit, status, abort)`,commandClass:to,category:`development`},{name:`loop`,description:`Run Claude Code in a loop, one task per iteration`,commandClass:ga,category:`development`},{name:`prime`,description:`Print task context and workflow rules for a coding agent`,commandClass:Gi,category:`development`},{name:`tags`,description:`Manage tags for task organization`,commandClass:ha,category:`task`},{name:`generate`,description:`Generate individual task files from tasks.json`,commandClass:no,category:`utility`},{name:`github`,description:`Push tasks to GitHub Issues (status, push, unlink)`,commandClass:yo,category:`utility`},{name:`completion`,description:`Set up Tab completion for bash, zsh or fish`,commandClass:Ka,category:`utility`}];static registerAll(e){for(let t of this.commands)this.registerCommand(e,t)}static registerByCategory(e,t){let n=this.commands.filter(e=>e.category===t);for(let t of n)this.registerCommand(e,t)}static registerByName(e,t){let n=this.commands.find(e=>e.name===t);if(n)this.registerCommand(e,n);else throw Error(`Command '${t}' not found in registry`)}static registerCommand(e,t){let n=t.commandClass;if(n.registerOn)n.registerOn(e);else if(n.register)n.register(e);else{let t=new n;e.addCommand(t)}}static getCommandNames(){return this.commands.map(e=>e.name)}static getCommandsByCategory(e){return this.commands.filter(t=>t.category===e)}static addCommand(e){if(this.commands.some(t=>t.name===e.name))throw Error(`Command '${e.name}' already exists in registry`);this.commands.push(e)}static removeCommand(e){let t=this.commands.findIndex(t=>t.name===e);return t>=0&&(this.commands.splice(t,1),!0)}static getCommand(e){return this.commands.find(t=>t.name===e)}static hasCommand(e){return this.commands.some(t=>t.name===e)}static getFormattedCommandList(){let e={task:`Task Management`,utility:`Utilities`,development:`Development`},t=``;for(let[n,r]of Object.entries(e)){let e=this.getCommandsByCategory(n);if(e.length>0){t+=`\n${r}:\n`;for(let n of e)t+=` ${n.name.padEnd(20)} ${n.description}\n`}}return t}};function xo(e){bo.registerAll(e)}function So(e,t,n){let r=t.filter(t=>t.allowed_roles.includes(e)),i=Math.max(0,...r.map(e=>e.id.length));return r.map(e=>{let t=[ti[e.id],e.id===n?`current`:void 0].filter(Boolean).join(` · `);return{name:t?`${e.id.padEnd(i)} ${x.muted(t)}`:e.id,value:e.id,short:e.id}})}function Co(e){let{label:t,purpose:n}=G[e];return`${t} model (${n})`}function wo(e,t){return`${w.green(`✔`)} ${w.bold(Co(e))} ${w.cyan(t)}`}async function To(e,t,n){let{model:r}=await Ue.createPromptModule({clearPromptOnDone:!0})([{type:`select`,name:`model`,message:Co(e),choices:t,default:n??void 0}]);return console.log(wo(e,r)),r}const Eo=[`main`,`research`,`fallback`];function Do(e){if(!e)throw Error(`Project root is required but not found.`);let t=le(null,{projectRoot:e}),n=ue(e);if(y(`debug`,`Checking for config file using findConfigPath, found: ${t}`),y(`debug`,`Checking config file using isConfigFilePresent(), exists: ${n}`),!n)throw Error(`The configuration file is missing. Run "taskgraph init" to create it.`)}function Oo(e){return(t,...n)=>{e&&typeof e[t]==`function`&&e[t](...n)}}async function ko(e={}){let{mcpLog:t,projectRoot:n}=e,r=Oo(t);Do(n);try{let e=xe(n),t=(t,n)=>{let r=e.find(e=>e.id===n&&e.provider===t);return{provider:t,modelId:n,sweScore:r?.swe_score||null,cost:r?.cost_per_1m_tokens||null}},r=pe(n);return{success:!0,data:{activeModels:{main:t(ye(n),Se(n)),research:t(Ee(n),Te(n)),fallback:r?t(r,we(n)):null},message:`Successfully retrieved current model configuration`}}}catch(e){return r(`error`,`Error getting model configuration: ${e.message}`),{success:!1,error:{code:`CONFIG_ERROR`,message:e.message}}}}async function Ao(e={}){let{mcpLog:t,projectRoot:n}=e,r=Oo(t);Do(n);try{let e=xe(n).map(e=>({provider:e.provider||`N/A`,modelId:e.id,sweScore:e.swe_score||null,cost:e.cost_per_1m_tokens||null,allowedRoles:e.allowed_roles||[]}));return{success:!0,data:{models:e,message:e.length?`Successfully retrieved ${e.length} available models`:`No available models found`}}}catch(e){return r(`error`,`Error getting available models: ${e.message}`),{success:!1,error:{code:`MODELS_LIST_ERROR`,message:e.message}}}}async function jo(e,t,n={}){let{mcpLog:r,projectRoot:i}=n,a=Oo(r);if(Do(i),!Eo.includes(e))return{success:!1,error:{code:`INVALID_ROLE`,message:`Invalid role: ${e}. Must be one of: ${Eo.join(`, `)}.`}};if(typeof t!=`string`||t.trim()===``)return{success:!1,error:{code:`INVALID_MODEL_ID`,message:`Invalid model ID: ${t}. Must be a non-empty string.`}};try{let n=o.CLAUDE_CODE,r=xe(i).filter(e=>e.provider===n),s=r.find(e=>e.id===t);if(!s)return{success:!1,error:{code:`MODEL_NOT_FOUND`,message:`Model ID "${t}" is not supported. TaskGraph uses Claude Code; valid models: ${r.map(e=>e.id).join(`, `)}.`}};let c=fe(i);if(c.models[e]={...c.models[e],provider:n,modelId:t},delete c.models[e].baseURL,s.max_tokens&&(c.models[e].maxTokens=s.max_tokens),!ve(c,i))return{success:!1,error:{code:`CONFIG_WRITE_ERROR`,message:`Error writing updated configuration to configuration file`}};let l=`Successfully set ${e} model to ${t} (Provider: ${n})`;return a(`info`,l),{success:!0,data:{role:e,provider:n,modelId:t,message:l}}}catch(t){return a(`error`,`Error setting ${e} model: ${t.message}`),{success:!1,error:{code:`SET_MODEL_ERROR`,message:t.message}}}}async function Mo(e){return ko(e)}async function No(e,t,n){return jo(e,t,n)}function Po(){return xe()}const Fo=e=>e instanceof Error&&e.name===`ExitPromptError`;async function Io(e){let t=await Mo({projectRoot:e}),n=t.success?t.data?.activeModels:void 0;return{main:n?.main?.modelId??null,research:n?.research?.modelId??null,fallback:n?.fallback?.modelId??null}}async function Lo(e,t){let n=[];for(let r of e){let e=await No(r.role,r.to,{projectRoot:t});if(!e.success)return J(`Couldn't set the ${r.role} model: ${e.error?.message??`unknown error`}`),{saved:n,ok:!1};n.push(r)}return{saved:n,ok:!0}}async function Ro(e){let t=await Io(e),n=Po().filter(e=>e.allowed_roles),r={};try{for(let e of W)r[e]=await To(e,So(e,n,t[e]),t[e])}catch(e){if(!Fo(e))throw e;return console.log(x.muted(`
489
+ Cancelled; no models changed`)),process.exitCode=130,!1}let i=W.filter(e=>r[e]&&r[e]!==t[e]).map(e=>({role:e,from:t[e],to:r[e]}));if(i.length===0)return!0;let{saved:a,ok:o}=await Lo(i,e);return a.length>0&&console.log(`\n${oi(a)}`),o||(process.exitCode=1),o}export{lt as $,ei as A,lr as B,J as C,oi as D,vi as E,gr as F,Gn as G,ur as H,vr as I,In as J,Bn as K,hr as L,jr as M,xr as N,ri as O,yr as P,Et as Q,_r as R,zi as S,gi as T,er as U,dr as V,Zn as W,B as X,yn as Y,Kt as Z,$i as _,xo as a,Xi as b,pa as c,da as d,ut as et,sa as f,ea as g,ta as h,jo as i,Yr as j,ii as k,aa as l,ca as m,Ao as n,ua as o,fa as p,Ln as q,ko as r,ia as s,Ro as t,ct as tt,la as u,Zi as v,Di as w,Y as x,Z as y,or as z};