ai-projects 1.4.0 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -122,22 +122,47 @@ declare const commands: {
122
122
  type: "pre-create" | "post-create" | "pre-complete" | "post-complete" | "pre-start" | "post-start" | "pre-update" | "post-update";
123
123
  }>>;
124
124
  };
125
+ readonly log: {
126
+ readonly append: CommandDef<zod.ZodObject<{
127
+ project: zod.ZodOptional<zod.ZodString>;
128
+ task: zod.ZodOptional<zod.ZodString>;
129
+ }, "strip", zod.ZodTypeAny, {
130
+ project?: string | undefined;
131
+ task?: string | undefined;
132
+ }, {
133
+ project?: string | undefined;
134
+ task?: string | undefined;
135
+ }>, zod.ZodObject<{
136
+ text: zod.ZodString;
137
+ }, "strip", zod.ZodTypeAny, {
138
+ text: string;
139
+ }, {
140
+ text: string;
141
+ }>>;
142
+ readonly read: CommandDef<zod.ZodObject<{
143
+ project: zod.ZodOptional<zod.ZodString>;
144
+ task: zod.ZodOptional<zod.ZodString>;
145
+ }, "strip", zod.ZodTypeAny, {
146
+ project?: string | undefined;
147
+ task?: string | undefined;
148
+ }, {
149
+ project?: string | undefined;
150
+ task?: string | undefined;
151
+ }>, zod.ZodObject<{}, "strip", zod.ZodTypeAny, {}, {}>>;
152
+ };
125
153
  readonly project: {
126
154
  readonly create: CommandDef<zod.ZodObject<{
127
155
  description: zod.ZodString;
128
156
  status: zod.ZodDefault<zod.ZodString>;
129
157
  assignee: zod.ZodOptional<zod.ZodString>;
130
- summary: zod.ZodOptional<zod.ZodString>;
131
158
  }, "strip", zod.ZodTypeAny, {
132
159
  status: string;
133
160
  description: string;
134
161
  assignee?: string | undefined;
135
- summary?: string | undefined;
136
162
  }, {
137
163
  description: string;
138
164
  status?: string | undefined;
139
165
  assignee?: string | undefined;
140
- summary?: string | undefined;
141
166
  }>, zod.ZodObject<{
142
167
  name: zod.ZodString;
143
168
  }, "strip", zod.ZodTypeAny, {
@@ -173,19 +198,16 @@ declare const commands: {
173
198
  description: zod.ZodOptional<zod.ZodString>;
174
199
  status: zod.ZodOptional<zod.ZodString>;
175
200
  assignee: zod.ZodOptional<zod.ZodString>;
176
- summary: zod.ZodOptional<zod.ZodString>;
177
201
  }, "strip", zod.ZodTypeAny, {
178
202
  status?: string | undefined;
179
203
  description?: string | undefined;
180
204
  name?: string | undefined;
181
205
  assignee?: string | undefined;
182
- summary?: string | undefined;
183
206
  }, {
184
207
  status?: string | undefined;
185
208
  description?: string | undefined;
186
209
  name?: string | undefined;
187
210
  assignee?: string | undefined;
188
- summary?: string | undefined;
189
211
  }>, zod.ZodObject<{
190
212
  project: zod.ZodOptional<zod.ZodString>;
191
213
  }, "strip", zod.ZodTypeAny, {
@@ -208,17 +230,14 @@ declare const commands: {
208
230
  description: zod.ZodOptional<zod.ZodString>;
209
231
  assignee: zod.ZodOptional<zod.ZodString>;
210
232
  status: zod.ZodDefault<zod.ZodString>;
211
- summary: zod.ZodOptional<zod.ZodString>;
212
233
  }, "strip", zod.ZodTypeAny, {
213
234
  status: string;
214
235
  description?: string | undefined;
215
236
  assignee?: string | undefined;
216
- summary?: string | undefined;
217
237
  }, {
218
238
  status?: string | undefined;
219
239
  description?: string | undefined;
220
240
  assignee?: string | undefined;
221
- summary?: string | undefined;
222
241
  }>, zod.ZodObject<{
223
242
  project: zod.ZodString;
224
243
  name: zod.ZodString;
@@ -305,21 +324,18 @@ declare const commands: {
305
324
  status: zod.ZodOptional<zod.ZodString>;
306
325
  assignee: zod.ZodOptional<zod.ZodString>;
307
326
  project: zod.ZodOptional<zod.ZodString>;
308
- summary: zod.ZodOptional<zod.ZodString>;
309
327
  }, "strip", zod.ZodTypeAny, {
310
328
  project?: string | undefined;
311
329
  status?: string | undefined;
312
330
  description?: string | undefined;
313
331
  name?: string | undefined;
314
332
  assignee?: string | undefined;
315
- summary?: string | undefined;
316
333
  }, {
317
334
  project?: string | undefined;
318
335
  status?: string | undefined;
319
336
  description?: string | undefined;
320
337
  name?: string | undefined;
321
338
  assignee?: string | undefined;
322
- summary?: string | undefined;
323
339
  }>, zod.ZodObject<{
324
340
  task: zod.ZodOptional<zod.ZodString>;
325
341
  }, "strip", zod.ZodTypeAny, {
package/dist/index.js CHANGED
@@ -1,26 +1,26 @@
1
1
  #!/usr/bin/env node
2
- import {z as z$1}from'zod';import {parser}from'zod-opts';import {spawn,exec}from'child_process';import J from'fs/promises';import T from'lodash';import B from'moment';import M from'path';import {fileURLToPath}from'url';import {inspect}from'util';import Ze from'dotenv';import Ve from'fs';import St from'yaml';var Fe=Object.defineProperty;var f=(t,e)=>()=>(t&&(e=t(t=0)),e);var He=(t,e)=>{for(var o in e)Fe(t,o,{get:e[o],enumerable:true});};var S,W=f(()=>{S={name:"ai-projects",version:"1.4.0",type:"module",description:"Useful CLI for AI agents to create and manage projects, tasks, skills and agents",main:"dist/index.js",types:"dist/index.d.ts",bin:{aip:"dist/index.js"},files:["dist/**/*","README.md","LICENSE"],scripts:{build:"npm run build:map && npm run build:code","build:map":"tsx bin/map-commands.ts","build:code":"tsup --no-dts","build:all":"npm run build:map && tsup","build:check":"tsc --noEmit","build:watch":"npm run build:code -- --watch","build:clean":"rimraf dist/*","build:incr":"tsup --no-dts",start:"dist/index.js",dev:'npm run build:watch -- --onSuccess "dist/index.js"',cli:"npm run build && npm start --",ts:"tsx",vitest:"VITE_CJS_IGNORE_WARNING=true vitest",test:"npm run test:types && npm run test:unit","test:unit":"npm run vitest -- run","test:types:test":"tsc -p tsconfig.test.json --incremental --tsBuildInfoFile dist/test.tsbuildinfo","test:types:bin":"tsc -p bin/tsconfig.json --incremental --tsBuildInfoFile dist/bin.tsbuildinfo","test:types":"npm run test:types:test && npm run test:types:bin","test:full":"npm run lint:full && npm run test",eslint:"eslint --cache",lint:"npm run eslint -- '{src,bin}/**/*.ts'","lint:fix":"npm run lint -- --fix","lint:full":"npm run build:incr && npm run test:types:bin && npm run lint:fix","lint:full:silent":"npm run -s lint:full && echo LINT OK",map:"npm run build:map",link:"npm link",unlink:"npm unlink",prepare:'[ "$CI" != "true" ] && [ -d node_modules/husky ] && husky || true',prepack:"npm run test:full && npm run build:all","publish:dry":"npm pack --dry-run","version:patch":"npm version patch","version:minor":"npm version minor","version:major":"npm version major"},keywords:["ai","aip","project","task","kanban","cli","agent","automation"],author:"Ariel Flesler <aflesler@gmail.com>",license:"MIT",repository:{type:"git",url:"git+https://github.com/flesler/ai-projects.git"},homepage:"https://github.com/flesler/ai-projects#readme",bugs:{url:"https://github.com/flesler/ai-projects/issues"},engines:{node:">=20.0.0"},dependencies:{dotenv:"^17.3.1",lodash:"^4.17.21",moment:"^2.30.1",tslib:"^2.8.1",yaml:"^2.8.0",zod:"^3.25.76","zod-opts":"^1.0.0"},devDependencies:{"@eslint/js":"^10.0.1","@stylistic/eslint-plugin":"^5.7.0","@types/dotenv":"^8.2.3","@types/eslint":"^9.6.1","@types/lodash":"^4.17.23","@types/moment":"^2.13.0","@types/node":"^25.0.9","@types/source-map-support":"^0.5.10","@typescript-eslint/eslint-plugin":"^8.53.0","@typescript-eslint/parser":"^8.53.0",eslint:"^10.0.3","eslint-plugin-import-x":"^4.16.2","eslint-plugin-unused-imports":"^4.4.1","fast-glob":"^3.3.3",husky:"^9.1.7",rimraf:"^6.0.1","source-map-support":"^0.5.21",tsup:"^8.5.1",tsx:"^4.20.3","types-package-json":"^2.0.39",typescript:"^5.8.3",vitest:"^4.0.17"}};});function p(t){let{description:e,options:o=z$1.object({}),args:r,handler:n}=t,i=o.shape,a={};for(let[u,l]of Object.entries(i))a[u]={type:l};let d=parser().options(a);if(r){let u=r.shape,l=Object.entries(u).map(([g,P])=>({name:g,type:P}));l.length>0&&(d=d.args(l));}return e&&(d=d.description(e)),{description:e,options:o,args:r,parser:d,handler:n,cli:u=>n(d.parse(u))}}var k=f(()=>{});var w,s,b=f(()=>{w={REPO:fileURLToPath(import.meta.url.replace(/\/(dist|src)\/.*/,"/")),join:(...t)=>M.join(...t),onRepo:(...t)=>w.join(w.REPO,...t),async ensureDir(t){await J.mkdir(t,{recursive:true});},async write(t,e){await w.ensureDir(M.dirname(t)),await J.writeFile(t,e,"utf8");},async read(t){return J.readFile(t,"utf8")},async readRepo(...t){return w.read(w.onRepo(...t))},async readMany(...t){return (await Promise.all(t.map(async o=>{if(await w.fileExists(o)){let r=await w.read(o);return `# ${o}
2
+ import {z as z$1}from'zod';import {parser}from'zod-opts';import Je from'dotenv';import Be from'fs';import F from'path';import {fileURLToPath}from'url';import {spawn,exec}from'child_process';import K from'fs/promises';import y from'lodash';import W from'moment';import {inspect}from'util';import Pt from'yaml';var He=Object.defineProperty;var f=(t,e)=>()=>(t&&(e=t(t=0)),e);var Ke=(t,e)=>{for(var o in e)He(t,o,{get:e[o],enumerable:true});};var b,B=f(()=>{b={name:"ai-projects",version:"1.5.1",type:"module",description:"Useful CLI for AI agents to create and manage projects, tasks, skills and agents",main:"dist/index.js",types:"dist/index.d.ts",bin:{aip:"dist/index.js"},files:["dist/**/*","README.md","LICENSE"],scripts:{build:"npm run build:map && npm run build:code","build:map":"tsx bin/map-commands.ts","build:code":"tsup --no-dts","build:all":"npm run build:map && tsup","build:check":"tsc --noEmit","build:watch":"npm run build:code -- --watch","build:clean":"rimraf dist/*","build:incr":"tsup --no-dts",start:"dist/index.js",dev:'npm run build:watch -- --onSuccess "dist/index.js"',cli:"npm run build && npm start --",ts:"tsx",vitest:"VITE_CJS_IGNORE_WARNING=true vitest",test:"npm run test:types && npm run test:unit","test:unit":"npm run vitest -- run","test:types:test":"tsc -p tsconfig.test.json --incremental --tsBuildInfoFile dist/test.tsbuildinfo","test:types:bin":"tsc -p bin/tsconfig.json --incremental --tsBuildInfoFile dist/bin.tsbuildinfo","test:types":"npm run test:types:test && npm run test:types:bin","test:full":"npm run lint:full && npm run test",eslint:"eslint --cache",lint:"npm run eslint -- '{src,bin}/**/*.ts'","lint:fix":"npm run lint -- --fix","lint:full":"npm run build:incr && npm run test:types:bin && npm run lint:fix","lint:full:silent":"npm run -s lint:full && echo LINT OK",map:"npm run build:map",link:"npm link",unlink:"npm unlink",prepare:'[ "$CI" != "true" ] && [ -d node_modules/husky ] && husky || true',prepack:"npm run test:full && npm run build:all","publish:dry":"npm pack --dry-run","version:patch":"npm version patch","version:minor":"npm version minor","version:major":"npm version major","agent:stop":"npm run -s lint:full:silent"},keywords:["ai","aip","project","task","kanban","cli","agent","automation"],author:"Ariel Flesler <aflesler@gmail.com>",license:"MIT",repository:{type:"git",url:"git+https://github.com/flesler/ai-projects.git"},homepage:"https://github.com/flesler/ai-projects#readme",bugs:{url:"https://github.com/flesler/ai-projects/issues"},engines:{node:">=20.0.0"},dependencies:{dotenv:"^17.3.1",lodash:"^4.17.21",moment:"^2.30.1",tslib:"^2.8.1",yaml:"^2.8.0",zod:"^3.25.76","zod-opts":"^1.0.0"},devDependencies:{"@eslint/js":"^10.0.1","@stylistic/eslint-plugin":"^5.7.0","@types/dotenv":"^8.2.3","@types/eslint":"^9.6.1","@types/lodash":"^4.17.23","@types/moment":"^2.13.0","@types/node":"^25.0.9","@types/source-map-support":"^0.5.10","@typescript-eslint/eslint-plugin":"^8.53.0","@typescript-eslint/parser":"^8.53.0",eslint:"^10.0.3","eslint-plugin-import-x":"^4.16.2","eslint-plugin-unused-imports":"^4.4.1","fast-glob":"^3.3.3",husky:"^9.1.7",rimraf:"^6.0.1","source-map-support":"^0.5.21",tsup:"^8.5.1",tsx:"^4.20.3","types-package-json":"^2.0.39",typescript:"^5.8.3",vitest:"^4.0.17"}};});function p(t){let{description:e,options:o=z$1.object({}),args:r,handler:s}=t,i=o.shape,a={};for(let[m,d]of Object.entries(i))a[m]={type:d};let l=parser().options(a);if(r){let m=r.shape,d=Object.entries(m).map(([k,P])=>({name:k,type:P}));d.length>0&&(l=l.args(d));}return e&&(l=l.description(e)),{description:e,options:o,args:r,parser:l,handler:s,cli:m=>s(l.parse(m))}}var g=f(()=>{});var c,$=f(()=>{c={dirs:{PROJECTS:"projects",SKILLS:"skills",AGENTS:"agents",TASKS:"tasks",INPUTS:"inputs",OUTPUTS:"outputs",HOOKS:"hooks",SCRIPTS:"scripts"},files:{MAIN:"main.md",STATUS:"status.tsv",LOG:"audit.log",SKILL:"SKILL.md"},hookTypes:["pre-create","post-create","pre-complete","post-complete","pre-start","post-start","pre-update","post-update"],languages:["ts","js","sh","py"],targets:["project","task"]};});var Ve,bt,N,Ze,E,H=f(()=>{$();Ve=()=>{let t=fileURLToPath(import.meta.url),e=F.dirname(t),o=10;for(let r=0;r<o;r++)try{if(Be.existsSync(F.join(e,"package.json")))return e;let s=F.dirname(e);if(s===e)break;e=s;}catch{break}return process.cwd()},bt=Ve(),N=process.env.AIP_HOME;N||(Je.config({path:F.join(bt,".env"),quiet:true}),N=process.env.AIP_HOME);if(!N){N=process.cwd();let t=N.split(F.sep);for(let e of [c.dirs.PROJECTS,c.dirs.SKILLS,c.dirs.AGENTS]){let o=t.indexOf(e);if(o!==-1){N=t.slice(0,o).join(F.sep);break}}}Ze={ROOT:bt,AIP_HOME:N},E=Ze;});var j,n,T=f(()=>{H();j={REPO:fileURLToPath(import.meta.url.replace(/\/(dist|src)\/.*/,"/")),join:(...t)=>F.join(...t),onRepo:(...t)=>j.join(j.REPO,...t),joinHome:(...t)=>j.join(E.AIP_HOME,...t),async ensureDir(t){await K.mkdir(t,{recursive:true});},async write(t,e){await j.ensureDir(F.dirname(t)),await K.writeFile(t,e,"utf8");},async append(t,e){await j.ensureDir(F.dirname(t)),await K.appendFile(t,e,"utf8");},async read(t){return K.readFile(t,"utf8")},async readRepo(...t){return j.read(j.onRepo(...t))},async readMany(...t){return (await Promise.all(t.map(async o=>{if(await j.fileExists(o)){let r=await j.read(o);return `# ${o}
3
3
 
4
- ${r}`}return ""}))).filter(Boolean)},async logFiles(...t){let e=await w.readMany(...t);console.log(e.join(`
4
+ ${r}`}return ""}))).filter(Boolean)},async logFiles(...t){let e=await j.readMany(...t);console.log(e.join(`
5
5
 
6
6
  ---
7
7
 
8
- `));},dumpCommandMapLines(t,e){let o=e?T.pick(t,e):t,r=[];for(let[n,i]of w.entriesOf(o))r.push(`${n} {${Object.keys(i).join("|")}}`);return r},async fileExists(t){try{return await J.access(t),!0}catch{return false}},async listDir(t){try{return await J.readdir(t)}catch{return []}},spawn:spawn,cd(t){process.chdir(t);},async exec(t,e){return new Promise(o=>{exec(t,{encoding:"utf8",...e},(r,n,i)=>{let a=r?.code;o({stdout:n??"",stderr:i??"",code:r?typeof a=="number"?a:1:0});});})},noop:()=>{},omitByDeep:(t,e)=>T.isArray(t)?t.map(o=>w.omitByDeep(o,e)):T.isPlainObject(t)?T.mapValues(T.omitBy(t,e),o=>w.omitByDeep(o,e)):t,omitNilsDeep:t=>w.omitByDeep(t,T.isNil),omitUndefinedsDeep:t=>w.omitByDeep(t,T.isUndefined),cloneDeep:t=>T.cloneDeep(t),int:t=>Number.parseInt(t,10),keysOf:t=>Object.keys(t),entriesOf:t=>Object.entries(t),isKeyOf:(t,e)=>!T.isNil(t)&&t in e,typeOf:t=>typeof t,never:{},undef:t=>t??void 0,toNull:t=>t??null,same:t=>t,notNil:t=>{if(T.isNil(t))throw new Error(`Received unexpected ${t} value`);return t},randomInt:(t,e)=>Math.floor(Math.random()*(e-t+1))+t,promise:()=>{let t,e=new Promise((o,r)=>{t={resolve:o,reject:r};});return T.extend(e,t)},isPromise:t=>T.isObject(t)&&"catch"in t,delay:t=>{let e=T.isObject(t)?w.toMS(t):t;return new Promise(o=>setTimeout(o,e))},promiseMap:(t,e)=>Promise.all(t.map(e)),promiseEach:(t,e)=>Promise.all(t.map(e)).then(()=>{}),memoize:t=>T.memoize(t,w.memoizeKey),toMS:t=>B.duration(t).asMilliseconds(),toSecs:t=>B.duration(t).asSeconds(),inspect:(t,e)=>inspect(t,{colors:false,showHidden:false,depth:null,compact:true,breakLength:1/0,...e}),stringify(t,e,o){let r=new WeakSet;return JSON.stringify(t,(n,i)=>{if(T.isObject(i)){if(r.has(i))return "[Circular]";r.add(i);}return T.isFunction(e)?e(n,i):i},o)},dump:t=>w.oneLine(w.stringify(t)),compactWhitespace:t=>t.replace(/\\n/g,`
8
+ `));},dumpCommandMapLines(t,e){let o=e?y.pick(t,e):t,r=[];for(let[s,i]of j.entriesOf(o))r.push(`${s} {${Object.keys(i).join("|")}}`);return r},async fileExists(t){try{return await K.access(t),!0}catch{return false}},async listDir(t){try{return await K.readdir(t)}catch{return []}},spawn:spawn,cd(t){process.chdir(t);},async exec(t,e){return new Promise(o=>{exec(t,{encoding:"utf8",...e},(r,s,i)=>{let a=r?.code;o({stdout:s??"",stderr:i??"",code:r?typeof a=="number"?a:1:0});});})},noop:()=>{},omitByDeep:(t,e)=>y.isArray(t)?t.map(o=>j.omitByDeep(o,e)):y.isPlainObject(t)?y.mapValues(y.omitBy(t,e),o=>j.omitByDeep(o,e)):t,omitNilsDeep:t=>j.omitByDeep(t,y.isNil),omitUndefinedsDeep:t=>j.omitByDeep(t,y.isUndefined),cloneDeep:t=>y.cloneDeep(t),int:t=>Number.parseInt(t,10),keysOf:t=>Object.keys(t),entriesOf:t=>Object.entries(t),isKeyOf:(t,e)=>!y.isNil(t)&&t in e,typeOf:t=>typeof t,never:{},undef:t=>t??void 0,toNull:t=>t??null,same:t=>t,notNil:t=>{if(y.isNil(t))throw new Error(`Received unexpected ${t} value`);return t},randomInt:(t,e)=>Math.floor(Math.random()*(e-t+1))+t,promise:()=>{let t,e=new Promise((o,r)=>{t={resolve:o,reject:r};});return y.extend(e,t)},isPromise:t=>y.isObject(t)&&"catch"in t,delay:t=>{let e=y.isObject(t)?j.toMS(t):t;return new Promise(o=>setTimeout(o,e))},promiseMap:(t,e)=>Promise.all(t.map(e)),promiseEach:(t,e)=>Promise.all(t.map(e)).then(()=>{}),memoize:t=>y.memoize(t,j.memoizeKey),toMS:t=>W.duration(t).asMilliseconds(),toSecs:t=>W.duration(t).asSeconds(),inspect:(t,e)=>inspect(t,{colors:false,showHidden:false,depth:null,compact:true,breakLength:1/0,...e}),stringify(t,e,o){let r=new WeakSet;return JSON.stringify(t,(s,i)=>{if(y.isObject(i)){if(r.has(i))return "[Circular]";r.add(i);}return y.isFunction(e)?e(s,i):i},o)},dump:t=>j.oneLine(j.stringify(t)),compactWhitespace:t=>t.replace(/\\n/g,`
9
9
  `).replace(/\r/g,"").replace(/[ \t]*\n[ \t]*/g,`
10
10
  `).replace(/\n{3,}/g,`
11
11
 
12
- `).replace(/ {2,}/g," ").trim(),oneLine:t=>t.replace(/\n/g,"\\n").replace(/\t/g,"\\t").replace(/ +/g," ").trim(),fuzzySearch:(t,e)=>T.includes(T.toLower(t||""),T.toLower(e||"")),elapsed:(t,e=Date.now())=>B.duration(B(e).diff(t||0)),iso:t=>B.utc(t).toISOString(),isoDate:t=>w.iso(t).slice(0,10),memoizeKey:(...t)=>t.join(""),exit:(t=0)=>{process.exit(t);},set:(t,e,o)=>(t[e]=o,t),run:async t=>{try{await t(),process.exit(0);}catch(e){console.error(e),process.exit(1);}},isMain:()=>{let t=process.argv[1]||"";return t.includes("/index.")||t.endsWith("/bin/aip")},errorMessage:t=>t instanceof Error?t.message:String(t),slugify:t=>t.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")},s=w;});var c,$=f(()=>{c={dirs:{PROJECTS:"projects",SKILLS:"skills",AGENTS:"agents",TASKS:"tasks",INPUTS:"inputs",OUTPUTS:"outputs",HOOKS:"hooks",SCRIPTS:"scripts"},files:{MAIN:"main.md",STATUS:"status.md",LOG:"audit.log",SKILL:"SKILL.md"},hookTypes:["pre-create","post-create","pre-complete","post-complete","pre-start","post-start","pre-update","post-update"],languages:["ts","js","sh","py"],targets:["project","task"]};});var Ye,bt,U,Qe,y,I=f(()=>{$();Ye=()=>{let t=fileURLToPath(import.meta.url),e=M.dirname(t),o=10;for(let r=0;r<o;r++)try{if(Ve.existsSync(M.join(e,"package.json")))return e;let n=M.dirname(e);if(n===e)break;e=n;}catch{break}return process.cwd()},bt=Ye(),U=process.env.AIP_HOME;U||(Ze.config({path:M.join(bt,".env"),quiet:true}),U=process.env.AIP_HOME);if(!U){U=process.cwd();let t=U.split(M.sep);for(let e of [c.dirs.PROJECTS,c.dirs.SKILLS,c.dirs.AGENTS]){let o=t.indexOf(e);if(o!==-1){U=t.slice(0,o).join(M.sep);break}}}Qe={ROOT:bt,AIP_HOME:U},y=Qe;});var xt,Z,dt,V,Et=f(()=>{b();xt=t=>{let e=t.trim();if(!e.startsWith("---"))return null;let o=e.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);return o?{frontmatter:St.parse(o[1]),content:o[2].trim()}:null},Z=async(t,e,o="")=>{let n=`---
13
- ${St.stringify(e).trim()}
12
+ `).replace(/ {2,}/g," ").trim(),oneLine:t=>t.replace(/\n/g,"\\n").replace(/\t/g,"\\t").replace(/ +/g," ").trim(),fuzzySearch:(t,e)=>y.includes(y.toLower(t||""),y.toLower(e||"")),elapsed:(t,e=Date.now())=>W.duration(W(e).diff(t||0)),iso:t=>W.utc(t).toISOString(),isoDate:t=>j.iso(t).slice(0,10),memoizeKey:(...t)=>t.join(""),exit:(t=0)=>{process.exit(t);},set:(t,e,o)=>(t[e]=o,t),run:async t=>{try{await t(),process.exit(0);}catch(e){console.error(e),process.exit(1);}},isMain:()=>{let t=process.argv[1]||"";return t.includes("/index.")||t.endsWith("/bin/aip")},errorMessage:t=>t instanceof Error?t.message:String(t),slugify:t=>t.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")},n=j;});var xt,V,ut,Z,$t=f(()=>{T();xt=t=>{let e=t.trim();if(!e.startsWith("---"))return null;let o=e.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);return o?{frontmatter:Pt.parse(o[1]),content:o[2].trim()}:null},V=async(t,e,o="")=>{let s=`---
13
+ ${Pt.stringify(e).trim()}
14
14
  ---
15
15
 
16
- ${o}`.trim();await s.write(t,n+`
17
- `);},dt=async(t,e)=>{let o=await s.read(t),r=xt(o);if(!r)throw new Error(`No frontmatter found in ${t}`);let n={...r.frontmatter,...e};return await Z(t,n,r.content),n},V=async t=>{let e=await s.read(t),o=xt(e);if(!o)throw new Error(`No frontmatter found in ${t}`);return o.frontmatter};});var K,X,At,$t,Xe,to,m,x=f(()=>{$();I();Et();b();K=(a=>(a.BACKLOG="backlog",a.IN_PROGRESS="in-progress",a.ONGOING="ongoing",a.DONE="done",a.BLOCKED="blocked",a.TO_DO="to-do",a))(K||{}),X=Object.values(K),At=["backlog","in-progress","ongoing"],$t=[c.dirs.HOOKS,c.dirs.INPUTS,c.dirs.OUTPUTS,c.dirs.SCRIPTS],Xe=[c.dirs.TASKS,...$t],to={getProjectDir(t){return s.join(y.AIP_HOME,c.dirs.PROJECTS,t)},getTaskDir(t,e){return s.join(this.getProjectDir(t),c.dirs.TASKS,e)},async findTask(t,e){if(e)return {project:e,task:t};let o=await this.listProjects(),r=[];if(await s.promiseEach(o,async n=>{(await this.listTasks(n)).includes(t)&&r.push(n);}),r.length===0)throw new Error(`Task '${t}' not found. Use --project to specify the project.`);if(r.length>1)throw new Error(`Task '${t}' found in multiple projects: ${r.join(", ")}. Use --project to specify which one.`);return {project:r[0],task:t}},getAgentDir(t){return s.join(y.AIP_HOME,c.dirs.AGENTS,t)},async listProjects(){let t=s.join(y.AIP_HOME,c.dirs.PROJECTS),e=await s.listDir(t);return (await s.promiseMap(e,async r=>{let n=this.getProjectDir(r);return await s.fileExists(n)&&r!==c.dirs.AGENTS?r:null})).filter(r=>r!==null).sort()},async listTasks(t){let e=s.join(this.getProjectDir(t),c.dirs.TASKS);return await s.fileExists(e)?await s.listDir(e):[]},async listAgents(){let t=s.join(y.AIP_HOME,c.dirs.AGENTS);return await s.fileExists(t)?await s.listDir(t):[]},async createProject(t,e){let o=this.getProjectDir(t);return await s.ensureDir(o),await Promise.all(Xe.map(r=>s.ensureDir(s.join(o,r)))),await Z(s.join(o,c.files.MAIN),e),await s.write(s.join(o,c.files.STATUS),""),o},async createTask(t,e,o){let r=this.getTaskDir(t,e);return await s.ensureDir(r),await Promise.all($t.map(n=>s.ensureDir(s.join(r,n)))),await Z(s.join(r,c.files.MAIN),o),await s.write(s.join(r,c.files.STATUS),""),r},async createAgent(t,e){let o=this.getAgentDir(t);return await s.ensureDir(o),await Z(s.join(o,c.files.MAIN),e),o},async getProject(t){let e=s.join(this.getProjectDir(t),c.files.MAIN);return await s.fileExists(e)?await V(e):null},async getTask(t,e){let o=s.join(this.getTaskDir(t,e),c.files.MAIN);return await s.fileExists(o)?await V(o):null},async getAgent(t){let e=s.join(this.getAgentDir(t),c.files.MAIN);return await s.fileExists(e)?await V(e):null},async updateProject(t,e){let o=s.join(this.getProjectDir(t),c.files.MAIN);return await dt(o,e)},async updateTask(t,e,o){let r=s.join(this.getTaskDir(t,e),c.files.MAIN);if((await V(r))?.status==="ongoing")throw new Error("Cannot update ongoing task. Should be done by user or update manually");return await dt(r,o)},async ingestTask(t,e){let o=this.getTaskDir(t,e),r=this.getProjectDir(t),n=[s.join(r,c.files.MAIN),s.join(o,c.files.MAIN),s.join(o,c.files.STATUS)];await s.logFiles(...n);},async ingestProject(t){let e=this.getProjectDir(t),o=await this.listTasks(t),r=[s.join(e,c.files.MAIN),s.join(e,c.files.STATUS),...o.map(n=>s.join(this.getTaskDir(t,n),c.files.MAIN))];await s.logFiles(...r);},async ingestFiles(t){await s.logFiles(...t);}},m=to;});var vt,Ot=f(()=>{k();b();x();vt=p({options:z$1.object({description:z$1.string().describe("Agent description"),status:z$1.string().default("active").describe("Initial status")}),args:z$1.object({name:z$1.string().describe("Agent name")}),handler:async({name:t,description:e,status:o})=>{let r=s.slugify(t);await m.createAgent(r,{name:t,description:e,status:o,created:new Date().toISOString()}),console.log(`Agent created: ${r}`),console.log(` Path: ${m.getAgentDir(r)}`);}});});var Dt,Ct=f(()=>{k();Dt=p({options:z$1.object({}),handler:async()=>{let t=process.env.CURRENT_AGENT;t||(console.error("CURRENT_AGENT not set"),process.exit(1)),console.log(t);}});});var It,Nt=f(()=>{k();x();It=p({options:z$1.object({}),handler:async()=>{let t=await m.listAgents(),e=[];for(let o of t){let r=await m.getAgent(o);r&&e.push({slug:o,name:r.name||o,status:r.status,description:r.description});}if(e.length===0){console.log("No agents found");return}console.log("Agents:"),console.log("---");for(let o of e)console.log(`${o.slug.padEnd(20)} ${o.name?.padEnd(30)||""} ${o.status||""} ${o.description||""}`);}});});var Rt,Ut=f(()=>{$();k();I();b();Rt=p({description:"Output agent directory path (for cd)",options:z$1.object({}),args:z$1.object({name:z$1.string().describe("Agent name (directory name)")}),handler:async({name:t})=>{let e=s.join(y.AIP_HOME,c.dirs.AGENTS,t),o=s.join(e,c.files.MAIN);if(!await s.fileExists(o))throw new Error(`Agent not found: ${t}
18
- Expected at: ${o}`);console.log(e);}});});var _t,Lt=f(()=>{$();k();I();b();_t=p({description:"Start an agent: read SOUL.md and AGENTS.md content",options:z$1.object({}),args:z$1.object({name:z$1.string().describe("Agent name (directory name)")}),handler:async({name:t})=>{let e=s.join(y.AIP_HOME,c.dirs.AGENTS,t),o=s.join(e,c.files.MAIN),r=s.join(e,"SOUL.md");if(!await s.fileExists(o))throw new Error(`Agent not found: ${t}
19
- Expected at: ${o}`);let i=[r,o];await s.logFiles(...i);}});});var Ft,Ht,so,Mt,Kt=f(()=>{k();Ft=t=>{let e=t.shape,o=[];for(let[r,n]of Object.entries(e)){let i=n._def,a="unknown",d,u;i.typeName==="ZodString"?a="string":i.typeName==="ZodNumber"?a="number":i.typeName==="ZodBoolean"?a="boolean":i.typeName==="ZodEnum"?a=`enum: ${i.values.join(" | ")}`:i.typeName==="ZodOptional"?a=Ht(i.innerType):i.typeName==="ZodDefault"&&(a=Ht(i.innerType),u=i.defaultValue()),i.description&&(d=i.description);let l=i.typeName!=="ZodOptional"&&i.typeName!=="ZodDefault";o.push({name:r,type:a,required:l,description:d,defaultValue:u});}return o},Ht=t=>{let e=t._def;return e.typeName==="ZodString"?"string":e.typeName==="ZodNumber"?"number":e.typeName==="ZodBoolean"?"boolean":e.typeName==="ZodEnum"?`enum: ${e.values.join(" | ")}`:"unknown"},so=(t,e,o)=>{let r=Ft(o.options),n=o.args?Ft(o.args):[],i=o.description,a=`\`${t} ${e}\``;if(i&&(a+=`: ${i}`),a+=`
20
- `,r.length>0||n.length>0){let u=[];for(let l of n){let g=l.required?`<${l.name}>`:`[${l.name}]`,P=l.description||"";l.defaultValue!==void 0&&(P+=P?` (default: ${l.defaultValue})`:`(default: ${l.defaultValue})`),u.push(`\xB7 ${g}${P?": "+P:""}`);}for(let l of r){let g=l.description||"";l.defaultValue!==void 0&&(g+=g?` (default: ${l.defaultValue})`:`(default: ${l.defaultValue})`),u.push(`\xB7 --${l.name}${g?": "+g:""}`);}a+=u.join(`
16
+ ${o}`.trim();await n.write(t,s+`
17
+ `);},ut=async(t,e)=>{let o=await n.read(t),r=xt(o);if(!r)throw new Error(`No frontmatter found in ${t}`);let s={...r.frontmatter,...e};return await V(t,s,r.content),s},Z=async t=>{let e=await n.read(t),o=xt(e);if(!o)throw new Error(`No frontmatter found in ${t}`);return o.frontmatter};});var M,et,vt,Et,to,eo,u,x=f(()=>{$();H();$t();T();M=(a=>(a.BACKLOG="backlog",a.IN_PROGRESS="in-progress",a.ONGOING="ongoing",a.DONE="done",a.BLOCKED="blocked",a.TO_DO="to-do",a))(M||{}),et=Object.values(M),vt=["backlog","in-progress","ongoing"],Et=[c.dirs.HOOKS,c.dirs.INPUTS,c.dirs.OUTPUTS,c.dirs.SCRIPTS],to=[c.dirs.TASKS,...Et],eo={getProjectDir(t){return n.joinHome(c.dirs.PROJECTS,t)},getTaskDir(t,e){return n.join(this.getProjectDir(t),c.dirs.TASKS,e)},async findTask(t,e){if(e)return {project:e,task:t};let o=await this.listProjects(),r=[];if(await n.promiseEach(o,async s=>{(await this.listTasks(s)).includes(t)&&r.push(s);}),r.length===0)throw new Error(`Task '${t}' not found. Use --project to specify the project.`);if(r.length>1)throw new Error(`Task '${t}' found in multiple projects: ${r.join(", ")}. Use --project to specify which one.`);return {project:r[0],task:t}},getAgentDir(t){return n.join(E.AIP_HOME,c.dirs.AGENTS,t)},async listProjects(){let t=n.join(E.AIP_HOME,c.dirs.PROJECTS),e=await n.listDir(t);return (await n.promiseMap(e,async r=>{let s=this.getProjectDir(r);return await n.fileExists(s)&&r!==c.dirs.AGENTS?r:null})).filter(r=>r!==null).sort()},async listTasks(t){let e=n.join(this.getProjectDir(t),c.dirs.TASKS);return await n.fileExists(e)?await n.listDir(e):[]},async listAgents(){let t=n.join(E.AIP_HOME,c.dirs.AGENTS);return await n.fileExists(t)?await n.listDir(t):[]},async createProject(t,e){let o=this.getProjectDir(t);return await n.ensureDir(o),await Promise.all(to.map(r=>n.ensureDir(n.join(o,r)))),await V(n.join(o,c.files.MAIN),e),await n.write(n.join(o,c.files.STATUS),""),o},async createTask(t,e,o){let r=this.getTaskDir(t,e);return await n.ensureDir(r),await Promise.all(Et.map(s=>n.ensureDir(n.join(r,s)))),await V(n.join(r,c.files.MAIN),o),await n.write(n.join(r,c.files.STATUS),""),r},async createAgent(t,e){let o=this.getAgentDir(t);return await n.ensureDir(o),await V(n.join(o,c.files.MAIN),e),o},async getProject(t){let e=n.join(this.getProjectDir(t),c.files.MAIN);return await n.fileExists(e)?await Z(e):null},async getTask(t,e){let o=n.join(this.getTaskDir(t,e),c.files.MAIN);return await n.fileExists(o)?await Z(o):null},async getAgent(t){let e=n.join(this.getAgentDir(t),c.files.MAIN);return await n.fileExists(e)?await Z(e):null},async updateProject(t,e){let o=n.join(this.getProjectDir(t),c.files.MAIN);return await ut(o,e)},async updateTask(t,e,o){let r=n.join(this.getTaskDir(t,e),c.files.MAIN);if((await Z(r))?.status==="ongoing")throw new Error("Cannot update ongoing task. Should be done by user or update manually");return await ut(r,o)},async ingestTask(t,e){let o=this.getTaskDir(t,e),r=this.getProjectDir(t),s=[n.join(r,c.files.MAIN),n.join(o,c.files.MAIN),n.join(o,c.files.STATUS)];await n.logFiles(...s);},async ingestProject(t){let e=this.getProjectDir(t),o=await this.listTasks(t),r=[n.join(e,c.files.MAIN),n.join(e,c.files.STATUS),...o.map(s=>n.join(this.getTaskDir(t,s),c.files.MAIN))];await n.logFiles(...r);},async ingestFiles(t){await n.logFiles(...t);}},u=eo;});var At,Dt=f(()=>{g();T();x();At=p({options:z$1.object({description:z$1.string().describe("Agent description"),status:z$1.string().default("active").describe("Initial status")}),args:z$1.object({name:z$1.string().describe("Agent name")}),handler:async({name:t,description:e,status:o})=>{let r=n.slugify(t);await u.createAgent(r,{name:t,description:e,status:o,created:new Date().toISOString()}),console.log(`Agent created: ${r}`),console.log(` Path: ${u.getAgentDir(r)}`);}});});var Ot,Ct=f(()=>{g();Ot=p({options:z$1.object({}),handler:async()=>{let t=process.env.CURRENT_AGENT;t||(console.error("CURRENT_AGENT not set"),process.exit(1)),console.log(t);}});});var Rt,Nt=f(()=>{g();x();Rt=p({options:z$1.object({}),handler:async()=>{let t=await u.listAgents(),e=[];for(let o of t){let r=await u.getAgent(o);r&&e.push({slug:o,name:r.name||o,status:r.status,description:r.description});}if(e.length===0){console.log("No agents found");return}console.log("Agents:"),console.log("---");for(let o of e)console.log(`${o.slug.padEnd(20)} ${o.name?.padEnd(30)||""} ${o.status||""} ${o.description||""}`);}});});var It,Ut=f(()=>{$();g();H();T();It=p({description:"Output agent directory path (for cd)",options:z$1.object({}),args:z$1.object({name:z$1.string().describe("Agent name (directory name)")}),handler:async({name:t})=>{let e=n.join(E.AIP_HOME,c.dirs.AGENTS,t),o=n.join(e,c.files.MAIN);if(!await n.fileExists(o))throw new Error(`Agent not found: ${t}
18
+ Expected at: ${o}`);console.log(e);}});});var _t,Lt=f(()=>{$();g();H();T();_t=p({description:"Start an agent: read SOUL.md and AGENTS.md content",options:z$1.object({}),args:z$1.object({name:z$1.string().describe("Agent name (directory name)")}),handler:async({name:t})=>{let e=n.join(E.AIP_HOME,c.dirs.AGENTS,t),o=n.join(e,c.files.MAIN),r=n.join(e,"SOUL.md");if(!await n.fileExists(o))throw new Error(`Agent not found: ${t}
19
+ Expected at: ${o}`);let i=[r,o];await n.logFiles(...i);}});});var Ft,Ht,no,Kt,Mt=f(()=>{g();Ft=t=>{let e=t.shape,o=[];for(let[r,s]of Object.entries(e)){let i=s._def,a="unknown",l,m;i.typeName==="ZodString"?a="string":i.typeName==="ZodNumber"?a="number":i.typeName==="ZodBoolean"?a="boolean":i.typeName==="ZodEnum"?a=`enum: ${i.values.join(" | ")}`:i.typeName==="ZodOptional"?a=Ht(i.innerType):i.typeName==="ZodDefault"&&(a=Ht(i.innerType),m=i.defaultValue()),i.description&&(l=i.description);let d=i.typeName!=="ZodOptional"&&i.typeName!=="ZodDefault";o.push({name:r,type:a,required:d,description:l,defaultValue:m});}return o},Ht=t=>{let e=t._def;return e.typeName==="ZodString"?"string":e.typeName==="ZodNumber"?"number":e.typeName==="ZodBoolean"?"boolean":e.typeName==="ZodEnum"?`enum: ${e.values.join(" | ")}`:"unknown"},no=(t,e,o)=>{let r=Ft(o.options),s=o.args?Ft(o.args):[],i=o.description,a=`\`${t} ${e}\``;if(i&&(a+=`: ${i}`),a+=`
20
+ `,r.length>0||s.length>0){let m=[];for(let d of s){let k=d.required?`<${d.name}>`:`[${d.name}]`,P=d.description||"";d.defaultValue!==void 0&&(P+=P?` (default: ${d.defaultValue})`:`(default: ${d.defaultValue})`),m.push(`\xB7 ${k}${P?": "+P:""}`);}for(let d of r){let k=d.description||"";d.defaultValue!==void 0&&(k+=k?` (default: ${d.defaultValue})`:`(default: ${d.defaultValue})`),m.push(`\xB7 --${d.name}${k?": "+k:""}`);}a+=m.join(`
21
21
  `)+`
22
22
  `;}return a+=`
23
- `,a},Mt=p({description:"Print generated CLI reference from command schemas",options:z$1.object({}),handler:async()=>{let{default:t}=await Promise.resolve().then(()=>(tt(),gt)),e="Prepend `aip` to each command\n\n",o=Object.keys(t).sort();for(let r of o){let n=t[r],i=Object.keys(n).sort();for(let a of i){let d=n[a];e+=so(r,a,d);}}console.log(e);}});});var io,Gt,zt=f(()=>{k();io=`# AIP Hooks
23
+ `,a},Kt=p({description:"Print generated CLI reference from command schemas",options:z$1.object({}),handler:async()=>{let{default:t}=await Promise.resolve().then(()=>(ot(),kt)),e="Prepend `aip` to each command\n\n",o=Object.keys(t).sort();for(let r of o){let s=t[r],i=Object.keys(s).sort();for(let a of i){let l=s[a];e+=no(r,a,l);}}console.log(e);}});});var ao,Gt,zt=f(()=>{g();ao=`# AIP Hooks
24
24
 
25
25
  Automated scripts that run before/after project/task actions.
26
26
 
@@ -62,7 +62,7 @@ Projects can include validation scripts and hooks to enforce folder semantics:
62
62
 
63
63
  - **\`hooks/pre-complete.sh\`** \u2013 Runs before task completion
64
64
  - Validates required files exist
65
- - Checks status.md has completion entry
65
+ - Checks status.tsv has completion entry
66
66
  - Runs structure validation (warning only)
67
67
  - Exit 1 blocks completion
68
68
 
@@ -113,9 +113,9 @@ if (!content.includes('description:')) {
113
113
  }
114
114
 
115
115
  // Require status update
116
- const statusPath = join(taskDir, 'status.md')
116
+ const statusPath = join(taskDir, 'status.tsv')
117
117
  if (!existsSync(statusPath) || readFileSync(statusPath, 'utf-8').length === 0) {
118
- console.error('\u274C status.md is empty')
118
+ console.error('\u274C status.tsv is empty')
119
119
  process.exit(1)
120
120
  }
121
121
  \`\`\`
@@ -183,7 +183,7 @@ DEBUG=1 aip task update --status done
183
183
  - Require tests before completion
184
184
  - Check outputs exist
185
185
  - Validate frontmatter fields
186
- - Ensure status.md updated
186
+ - Ensure status.tsv updated
187
187
 
188
188
  ### Automation
189
189
  - Backup before changes
@@ -200,26 +200,26 @@ DEBUG=1 aip task update --status done
200
200
  ---
201
201
 
202
202
  *Hooks automate workflow enforcement. Pre-hooks guard quality, post-hooks handle cleanup.*
203
- `,Gt=p({description:"Hook types, env vars, and patterns",options:z$1.object({}),handler:async()=>{console.log(io);}});});var D,co,Wt,Jt=f(()=>{W();k();D=Object.keys(S.bin)[0],co=`# Quick Start
203
+ `,Gt=p({description:"Hook types, env vars, and patterns",options:z$1.object({}),handler:async()=>{console.log(ao);}});});var A,po,Jt,Bt=f(()=>{B();g();A=Object.keys(b.bin)[0],po=`# Quick Start
204
204
 
205
205
  ## New Task/Project
206
206
 
207
207
  \`\`\`bash
208
208
  # 1. Create project (if needed)
209
- ${D} project create "my-project" --description "What I'm building"
209
+ ${A} project create "my-project" --description "What I'm building"
210
210
 
211
211
  # 2. Create task
212
- ${D} task create my-project "first-task" --description "Start here"
212
+ ${A} task create my-project "first-task" --description "Start here"
213
213
 
214
214
  # 3. Navigate to task
215
- cd $(${D} task path first-task)
215
+ cd $(${A} task path first-task)
216
216
 
217
217
  # 4. Start working (implicit from PWD)
218
- ${D} task start
219
- # \u2192 sets status to in-progress
218
+ ${A} task start
219
+ # \u2192 sets status to in-progress, reads all context to stdout
220
220
 
221
221
  # 5. Work session
222
- # Log progress: ${D} task update --summary "API integration complete"
222
+ # Log progress: ${A} log append "API integration complete"
223
223
  # Save: outputs/ to deliver, inputs/ for data
224
224
  \`\`\`
225
225
 
@@ -227,20 +227,27 @@ ${D} task start
227
227
 
228
228
  \`\`\`bash
229
229
  # Find your tasks (searches all projects)
230
- ${D} task list
230
+ ${A} task list
231
231
 
232
232
  # Navigate to task
233
- cd $(${D} task path task-slug)
233
+ cd $(${A} task path task-slug)
234
234
 
235
235
  # All commands work implicitly from PWD:
236
- ${D} task start # Start working (sets status to in-progress)
236
+ ${A} task start # Start working (sets status to in-progress, reads all context to stdout)
237
237
  \`\`\`
238
238
 
239
239
  ## Completing
240
240
 
241
241
  \`\`\`bash
242
242
  # Mark done (implicit from PWD)
243
- ${D} task update --status done --summary "What I built"
243
+ ${A} task update --status done
244
+ ${A} log append "if you want to log something extra"
245
+ \`\`\`
246
+
247
+ ## Check current task
248
+
249
+ \`\`\`bash
250
+ ${A} task current
244
251
  \`\`\`
245
252
 
246
253
  **Note:** All task commands accept an optional task slug, but use PWD if not provided. Navigate with \`cd\` first for smoother workflow.
@@ -250,15 +257,19 @@ ${D} task update --status done --summary "What I built"
250
257
  \`\`\`
251
258
  $AIP_HOME/projects/slug/
252
259
  \u251C\u2500\u2500 main.md # Goals (read first)
253
- \u251C\u2500\u2500 status.md # Log (append every session)
260
+ \u251C\u2500\u2500 status.tsv # Log (append every session)
254
261
  \u2514\u2500\u2500 tasks/task/
255
262
  \u251C\u2500\u2500 main.md # Task definition
256
- \u2514\u2500\u2500 status.md # Updates
263
+ \u2514\u2500\u2500 status.tsv # Updates
257
264
  \`\`\`
258
265
 
259
- **Status format:** \`[YYYY-MM-DD HH:MM] message\`
260
- **Example:** \`[2026-03-30 14:30] API integration complete\`
261
- `,Wt=p({description:"Quick start guide for new users",options:z$1.object({}),handler:async()=>{console.log(co);}});});var po,lo,Zt,Vt,qt,Yt,Qt,et,ot,kt,Xt,te=f(()=>{W();$();k();x();po=Object.values(K).join("|"),{PROJECTS:lo,TASKS:Zt,HOOKS:Vt,INPUTS:qt,OUTPUTS:Yt,SCRIPTS:Qt}=c.dirs,{MAIN:et,STATUS:ot}=c.files,kt=`# AIP - Project Management Skill
266
+ **Status format:** TSV with columns: date, time, entityType, slug, action, text
267
+ **Example:** \`2026-03-30<TAB>14:30:00<TAB>task<TAB>api-integration<TAB>log<TAB>API integration complete\`
268
+
269
+ ## Commands
270
+
271
+ Run \`${A} help usage\` for all commands.
272
+ `,Jt=p({description:"Quick start guide for new users",options:z$1.object({}),handler:async()=>{console.log(po);}});});var lo,mo,uo,fo,go,ko,ho,Vt,Zt,G,ht,qt,Yt=f(()=>{B();$();g();x();lo=Object.values(M).join("|"),{PROJECTS:mo,TASKS:uo,HOOKS:fo,INPUTS:go,OUTPUTS:ko,SCRIPTS:ho}=c.dirs,{MAIN:Vt,STATUS:Zt}=c.files,G=Object.keys(b.bin)[0],ht=`# AIP - Project Management Skill
262
273
 
263
274
  Automated project and task creation with proper structure, front-matter, and file organization.
264
275
 
@@ -266,164 +277,70 @@ Automated project and task creation with proper structure, front-matter, and fil
266
277
 
267
278
  Streamline creation of new projects and tasks with the correct directory structure, file templates, and front-matter. Ensures consistency across all autonomous work.
268
279
 
269
- ## File Structure
280
+ ## Quick Start
270
281
 
271
- Every project follows this structure:
282
+ - New user? Run: \`${G} help quickstart\`
283
+ - All commands? Run: \`${G} help usage\`
284
+ - Just for one noun? Run: \`${G} help usage <noun>\` (e.g., \`${G} help usage task\`)
285
+ - Need EVERYTHING (big)? Run: \`${G} help api\` - Shows all commands with full option details
286
+
287
+ ## File Structure Overview
272
288
 
273
289
  \`\`\`
274
- $AIP_HOME/${lo}/{project-slug}/
275
- \u251C\u2500\u2500 ${et} # Primary context: goals, objectives, scope, data
276
- \u251C\u2500\u2500 ${ot} # Chronological log of status updates
277
- \u251C\u2500\u2500 ${Vt}/ # pre|post-{create,start,update,complete}.*
278
- \u251C\u2500\u2500 ${Yt}/ # Deliverables (reports, code, final files)
279
- \u251C\u2500\u2500 ${qt}/ # External data (API responses, downloads)
280
- \u251C\u2500\u2500 ${Qt}/ # Automation (bash/python/js)
281
- \u2514\u2500\u2500 ${Zt}/
290
+ $AIP_HOME/${mo}/{project-slug}/
291
+ \u251C\u2500\u2500 ${Vt} # Primary context: goals, scope, data
292
+ \u251C\u2500\u2500 ${Zt} # Chronological log (TSV: date, time, entityType, slug, action, text)
293
+ \u251C\u2500\u2500 ${fo}/ # pre|post-{create,start,update,complete}.*
294
+ \u251C\u2500\u2500 ${ko}/ # Deliverables
295
+ \u251C\u2500\u2500 ${go}/ # External data
296
+ \u251C\u2500\u2500 ${ho}/ # Automation
297
+ \u2514\u2500\u2500 ${uo}/
282
298
  \u2514\u2500\u2500 {task-slug}/
283
- \u251C\u2500\u2500 ${et} # Task definition with front-matter
284
- \u251C\u2500\u2500 ${ot} # Single-line updates per work session
285
- \u251C\u2500\u2500 ${Vt}/ # Task-level hooks
286
- \u251C\u2500\u2500 ${Yt}/ # Task-specific deliverables
287
- \u251C\u2500\u2500 ${qt}/ # Task-specific data files
288
- \u2514\u2500\u2500 ${Qt}/ # Task-specific automation
299
+ \u251C\u2500\u2500 ${Vt} # Task definition
300
+ \u251C\u2500\u2500 ${Zt} # Activity log
301
+ \u2514\u2500\u2500 ... (same structure)
289
302
  \`\`\`
290
303
 
291
- ## File Purposes
292
-
293
- ### \`main.md\` - Primary Context (Read First)
294
- **What goes here:**
295
- - Project/task objectives and goals
296
- - Scope and success criteria
297
- - Background information and context
298
- - Requirements and constraints
299
- - Reference information
304
+ ## Front-matter Format
300
305
 
301
- **Front-matter:**
302
306
  \`\`\`yaml
303
307
  ---
304
308
  name: Clear Title
305
- description: One-line summary for search
309
+ description: One-line summary
306
310
  assignee: agent-name
307
- status: ${po}
311
+ status: ${lo}
308
312
  created: YYYY-MM-DD
309
313
  ---
310
314
  \`\`\`
311
315
 
312
- **When to read:** Always first, before starting work
313
-
314
- **When to update:** Only when scope/goals change (rare)
315
-
316
- ### \`status.md\` - Activity Log (Append Only)
317
- **What goes here:** Single-line timestamped entries
318
-
319
- **Task examples:**
320
- \`\`\`markdown
321
- [2026-03-17 14:30] Task created: optimize-config
322
- [2026-03-17 15:45] Updated: status=in-progress
323
- [2026-03-17 16:20] API integration complete
324
- \`\`\`
325
-
326
- **Project example:**
327
- \`\`\`markdown
328
- [2026-03-17 16:00] Task completed: gather-requirements (details: tasks/gather-requirements/)
329
- \`\`\`
330
-
331
- **When to update:** Every work session (tasks) or task completion (projects)
332
-
333
- ### \`outputs/\` - Deliverables
334
- **What:** Final deliverables (reports, code, data)
335
- **Examples:** \`outputs/report.md\`, \`outputs/code.zip\`
336
-
337
- ### \`inputs/\` - External Data
338
- **What:** External data (API responses, downloads)
339
- **Examples:** \`inputs/api.json\`, \`inputs/data.csv\`
340
-
341
- ### \`scripts/\` - Automation
342
- **What:** Automation scripts (bash, python, js)
343
- **Examples:** \`scripts/deploy.sh\`, \`scripts/process.py\`
344
-
345
- ## Usage
346
-
347
- ### Create New Project
348
-
349
- \`\`\`bash
350
- # Via AIP CLI
351
- aip project create "optimize-hermes-config" \\
352
- --description "Analyze and optimize Hermes Agent configuration" \\
353
- --assignee basic
354
- \`\`\`
355
-
356
- ### Create New Task in Existing Project
357
-
358
- \`\`\`bash
359
- aip task create "optimize-hermes-config" "apply-config-changes" \\
360
- --description "Implement safe optimizations" \\
361
- --assignee basic
362
- \`\`\`
363
-
364
- ### Navigate to Project/Task
365
-
366
- \`\`\`bash
367
- cd $(aip project path optimize-hermes-config)
368
- cd $(aip task path apply-config-changes)
369
- \`\`\`
370
-
371
- ### Update Task Status (implicit from PWD)
372
-
373
- \`\`\`bash
374
- aip task update --status done
375
- aip task update --summary "Completed implementation"
376
- \`\`\`
377
-
378
- **Note:** All task commands accept optional task slug, but use PWD if not provided. Navigate with \`cd\` first for smoother workflow.
379
-
380
- ## Work Session
381
-
382
- 1. **Read:** \`main.md\` + \`status.md\`
383
- 2. **Work:** Save data to \`inputs/\`, deliverables to \`outputs/\`
384
- 3. **Log:** Append to \`status.md\`: \`[timestamp] message\`
385
- 4. **Complete:** Set status=\`done\`, summarize to project \`status.md\`
386
-
387
316
  ## Best Practices
388
317
 
389
- **DO:** Concise status entries, update every session
390
- **DON'T:** Long paragraphs, mix inputs/outputs
318
+ **DO:** Concise status entries, update every session, save deliverables to outputs/
319
+ **DON'T:** Long paragraphs in status, mix inputs/outputs
391
320
 
392
- **Front-matter:** \`name\`, \`description\`, \`assignee\`, \`status\`, \`created\`
321
+ ## For Agents
393
322
 
394
- ## Example
395
-
396
- \`\`\`
397
- $AIP_HOME/projects/my-project/
398
- \u251C\u2500\u2500 ${et} # Goals, context
399
- \u251C\u2500\u2500 ${ot} # Activity log
400
- \u2514\u2500\u2500 ${Zt}/
401
- \u2514\u2500\u2500 task-1/
402
- \u251C\u2500\u2500 ${et} # Task definition
403
- \u2514\u2500\u2500 ${ot} # Updates
404
- \`\`\`
405
-
406
- **Status log:**
407
- \`\`\`markdown
408
- [2026-03-17 09:00] Task created: implement-api
409
- [2026-03-17 10:30] Updated: status=in-progress
410
- [2026-03-17 12:00] Tests passing
411
- \`\`\`
412
- `,Xt=p({description:"Project management skill for creating and managing projects/tasks",options:z$1.object({mode:z$1.enum(["md","claude","hermes"]).default("md").describe("Output format: md (no header), claude (name+description), hermes (full frontmatter)")}),handler:async t=>{let e=Object.keys(S.bin)[0];if(t.mode==="md"){console.log(kt);return}if(t.mode==="claude"){console.log(`---
323
+ When working on a task:
324
+ 1. Read \`main.md\` first (goals/context)
325
+ 2. Review \`status.tsv\` (activity history)
326
+ 3. Work and save outputs to \`outputs/\`
327
+ 4. Log progress: \`${G} log append "message"\`
328
+ 5. On completion: set status=\`done\`, log summary
329
+ `,qt=p({description:"Project management skill for creating and managing projects/tasks",options:z$1.object({mode:z$1.enum(["md","claude","hermes"]).default("md").describe("Output format: md (no header), claude (name+description), hermes (full frontmatter)")}),handler:async t=>{let e=Object.keys(b.bin)[0];if(t.mode==="md"){console.log(ht);return}if(t.mode==="claude"){console.log(`---
413
330
  name: ${e}
414
- description: ${S.description}
415
- ---`),console.log(),console.log(kt);return}if(t.mode==="hermes"){console.log(`---
331
+ description: ${b.description}
332
+ ---`),console.log(),console.log(ht);return}if(t.mode==="hermes"){console.log(`---
416
333
  name: ${e}
417
- description: ${S.description}
418
- version: ${S.version}
419
- author: ${S.author}
420
- license: ${S.license}
334
+ description: ${b.description}
335
+ version: ${b.version}
336
+ author: ${b.author}
337
+ license: ${b.license}
421
338
  metadata:
422
339
  hermes:
423
- tags: [${S.keywords.join(", ")}]
424
- ---`),console.log(),console.log(kt);return}}});});var ee,oe=f(()=>{W();k();b();ee=p({description:"Print compact CLI usage (all nouns, or one noun if name is given)",options:z$1.object({}),args:z$1.object({name:z$1.string().optional().describe("Noun (e.g. task) to list verbs for")}),handler:async({name:t})=>{let{default:e}=await Promise.resolve().then(()=>(tt(),gt)),o=`${S.name} ${S.version} -`,r=s.dumpCommandMapLines(e,t);if(!t)console.log(o,"Usage: aip <noun> <verb> [options]"),console.log(r.map(n=>`-> ${n}`).join(`
425
- `)),console.log(),console.log("Run `aip help quickstart` for a quick start guide"),console.log("Run `aip help skill` for a broader overview");else {let n=r[0]??`${t} {?}`;console.log(o,`Usage: aip ${n} [options]`);}}});});var yt,mo,j,v=f(()=>{$();I();b();yt=s.join(y.AIP_HOME,c.dirs.PROJECTS),mo={getProjectFromPwd(t=process.cwd()){let e=M.relative(yt,t);if(!e||e.startsWith(".."))return null;let o=e.split(M.sep).filter(Boolean);return o.length===0?null:o[0]},getTaskFromPwd(t=process.cwd()){let e=M.relative(yt,t);if(!e||e.startsWith(".."))return null;let o=e.split(M.sep).filter(Boolean);return o.length<3||o[1]!==c.dirs.TASKS?null:o[2]},getCurrentContext(t=process.cwd()){return {project:this.getProjectFromPwd(t),task:this.getTaskFromPwd(t)}},requireProject(t=process.cwd()){let e=this.getProjectFromPwd(t);if(!e)throw new Error(`Not in a project directory. PWD: ${t}, projects: ${yt}`);return e},requireTask(t=process.cwd()){let e=this.getCurrentContext(t);if(!e.project||!e.task)throw new Error(`Not in a task directory. PWD: ${t}`);return {project:e.project,task:e.task}},exportContext(t=process.cwd()){let e=this.getCurrentContext(t),o=[];return e.project&&o.push(`export CURRENT_PROJECT="${e.project}"`),e.task&&o.push(`export CURRENT_TASK="${e.task}"`),process.env.CURRENT_AGENT&&o.push(`export CURRENT_AGENT="${process.env.CURRENT_AGENT}"`),o.join(`
426
- `)},getTargetDir(t,e=process.cwd()){let o=this.getCurrentContext(e);if(t==="project"){let r=this.getProjectFromPwd(e);if(!r)throw new Error("Not in a project directory. Use --project flag or cd into a project.");let n=s.join(y.AIP_HOME,c.dirs.PROJECTS,r);return {targetDir:n,projectDir:n,entityType:"project"}}if(t==="task"){if(!o.project||!o.task)throw new Error("Not in a task directory. Use --project and --task flags or cd into a task.");let r=s.join(y.AIP_HOME,c.dirs.PROJECTS,o.project);return {targetDir:s.join(r,c.dirs.TASKS,o.task),projectDir:r,entityType:"task"}}if(o.task&&o.project){let r=s.join(y.AIP_HOME,c.dirs.PROJECTS,o.project);return {targetDir:s.join(r,c.dirs.TASKS,o.task),projectDir:r,entityType:"task"}}if(o.project){let r=s.join(y.AIP_HOME,c.dirs.PROJECTS,o.project);return {targetDir:r,projectDir:r,entityType:"project"}}throw new Error("Not in a project or task directory. Specify --target flag.")}},j=mo;});var re,se=f(()=>{k();b();v();$();re=p({options:z$1.object({lang:z$1.enum(c.languages).default("ts").describe("Language"),target:z$1.enum(c.targets).default("project").describe("Target level")}),args:z$1.object({type:z$1.enum(c.hookTypes).describe("Hook type (e.g., pre-create, post-complete)")}),handler:async({type:t,lang:e,target:o})=>{let r=e,n=`.${r}`,{targetDir:i,entityType:a}=j.getTargetDir(o),d=s.join(i,c.dirs.HOOKS);await s.ensureDir(d);let u=s.join(d,`${t}${n}`);if(await s.fileExists(u))throw new Error(`Hook already exists: ${u}`);let g;if(r==="ts")g=`#!/usr/bin/env tsx
340
+ tags: [${b.keywords.join(", ")}]
341
+ ---`),console.log(),console.log(ht);return}}});});var Qt,Xt=f(()=>{B();g();T();Qt=p({description:"Print compact CLI usage (all nouns, or one noun if name is given)",options:z$1.object({}),args:z$1.object({name:z$1.string().optional().describe("Noun (e.g. task) to list verbs for")}),handler:async({name:t})=>{let{default:e}=await Promise.resolve().then(()=>(ot(),kt)),o=`${b.name} ${b.version} -`,r=n.dumpCommandMapLines(e,t);if(!t)console.log(o,"Usage: aip <noun> <verb> [options]"),console.log(r.map(s=>`-> ${s}`).join(`
342
+ `)),console.log(),console.log("Run `aip help quickstart` for a quick start guide"),console.log("Run `aip help skill` for a broader overview");else {let s=r[0]??`${t} {?}`;console.log(o,`Usage: aip ${s} [options]`);}}});});var yt,jo,h,D=f(()=>{$();T();yt=n.joinHome(c.dirs.PROJECTS),jo={getProjectFromPwd(t=process.cwd()){let e=F.relative(yt,t);if(!e||e.startsWith(".."))return null;let o=e.split(F.sep).filter(Boolean);return o.length===0?null:o[0]},getTaskFromPwd(t=process.cwd()){let e=F.relative(yt,t);if(!e||e.startsWith(".."))return null;let o=e.split(F.sep).filter(Boolean);return o.length<3||o[1]!==c.dirs.TASKS?null:o[2]},getCurrentContext(t=process.cwd()){return {project:this.getProjectFromPwd(t),task:this.getTaskFromPwd(t)}},requireProject(t=process.cwd()){let e=this.getProjectFromPwd(t);if(!e)throw new Error(`Not in a project directory. PWD: ${t}, projects: ${yt}`);return e},requireTask(t=process.cwd()){let e=this.getCurrentContext(t);if(!e.project||!e.task)throw new Error(`Not in a task directory. PWD: ${t}`);return {project:e.project,task:e.task}},exportContext(t=process.cwd()){let e=this.getCurrentContext(t),o=[];return e.project&&o.push(`export CURRENT_PROJECT="${e.project}"`),e.task&&o.push(`export CURRENT_TASK="${e.task}"`),process.env.CURRENT_AGENT&&o.push(`export CURRENT_AGENT="${process.env.CURRENT_AGENT}"`),o.join(`
343
+ `)},getTargetDir(t,e=process.cwd()){let o=this.getCurrentContext(e);if(t==="project"){let r=this.getProjectFromPwd(e);if(!r)throw new Error("Not in a project directory. Use --project flag or cd into a project.");let s=n.joinHome(c.dirs.PROJECTS,r);return {targetDir:s,projectDir:s,entityType:"project"}}if(t==="task"){if(!o.project||!o.task)throw new Error("Not in a task directory. Use --project and --task flags or cd into a task.");let r=n.joinHome(c.dirs.PROJECTS,o.project);return {targetDir:n.join(r,c.dirs.TASKS,o.task),projectDir:r,entityType:"task"}}if(o.task&&o.project){let r=n.joinHome(c.dirs.PROJECTS,o.project);return {targetDir:n.join(r,c.dirs.TASKS,o.task),projectDir:r,entityType:"task"}}if(o.project){let r=n.joinHome(c.dirs.PROJECTS,o.project);return {targetDir:r,projectDir:r,entityType:"project"}}throw new Error("Not in a project or task directory. Specify --target flag.")}},h=jo;});var te,ee=f(()=>{g();T();D();$();te=p({options:z$1.object({lang:z$1.enum(c.languages).default("ts").describe("Language"),target:z$1.enum(c.targets).default("project").describe("Target level")}),args:z$1.object({type:z$1.enum(c.hookTypes).describe("Hook type (e.g., pre-create, post-complete)")}),handler:async({type:t,lang:e,target:o})=>{let r=e,s=`.${r}`,{targetDir:i,entityType:a}=h.getTargetDir(o),l=n.join(i,c.dirs.HOOKS);await n.ensureDir(l);let m=n.join(l,`${t}${s}`);if(await n.fileExists(m))throw new Error(`Hook already exists: ${m}`);let k;if(r==="ts")k=`#!/usr/bin/env tsx
427
344
  /** ${t} hook for ${a} */
428
345
 
429
346
  import { env } from 'node:process'
@@ -436,7 +353,7 @@ if (env.TASK_SLUG) {
436
353
 
437
354
  // Exit with non-zero to prevent action (for pre-hooks)
438
355
  // process.exit(1)
439
- `;else if(r==="js")g=`#!/usr/bin/env node
356
+ `;else if(r==="js")k=`#!/usr/bin/env node
440
357
  /** ${t} hook for ${a} */
441
358
 
442
359
  console.log('Running ${t} hook for ${a}')
@@ -447,7 +364,7 @@ if (process.env.TASK_SLUG) {
447
364
 
448
365
  // Exit with non-zero to prevent action (for pre-hooks)
449
366
  // process.exit(1)
450
- `;else if(r==="sh")g=`#!/bin/bash
367
+ `;else if(r==="sh")k=`#!/bin/bash
451
368
  # ${t} hook for ${a}
452
369
 
453
370
  echo "Running ${t} hook for ${a}"
@@ -458,7 +375,7 @@ fi
458
375
 
459
376
  # Exit with non-zero to prevent action (for pre-hooks)
460
377
  # exit 1
461
- `;else if(r==="py")g=`#!/usr/bin/env python3
378
+ `;else if(r==="py")k=`#!/usr/bin/env python3
462
379
  """${t} hook for ${a}"""
463
380
 
464
381
  import os
@@ -470,13 +387,13 @@ if os.environ.get('TASK_SLUG'):
470
387
 
471
388
  # Exit with non-zero to prevent action (for pre-hooks)
472
389
  # sys.exit(1)
473
- `;else throw new Error(`Unsupported language: ${r}`);await s.write(u,g);let{chmod:P}=await import('fs/promises');await P(u,493),console.log(`Hook created: ${u}`);}});});var fo,E,G=f(()=>{$();I();b();fo={async findHooks(t,e){let o=s.join(t,c.dirs.HOOKS);if(!await s.fileExists(o))return [];let n=await s.listDir(o),i=`${e}.`;return n.filter(a=>a.startsWith(i)).map(a=>s.join(o,a))},async executeHook(t,e,o){if(!await s.fileExists(t))return true;let n=e.project?s.join(y.AIP_HOME,c.dirs.PROJECTS,e.project):o,i=e.task?s.join(n,c.dirs.TASKS,e.task):"",a={...process.env,HOOK_TYPE:e.action,ENTITY_TYPE:e.entityType,TARGET_DIR:o,PROJECT_DIR:n,...e.project?{PROJECT_SLUG:e.project}:{},...e.task?{TASK_SLUG:e.task,TASK_DIR:i}:{}};return new Promise(d=>{let u=spawn(t,[],{stdio:"inherit",env:a,cwd:M.dirname(t),shell:false});u.on("close",(l,g)=>{l===0?d(true):(console.error(`Hook ${M.basename(t)} failed (code=${l??g})`),d(false));}),u.on("error",l=>{console.error(`Failed to execute hook ${t}: ${l.message}`),d(false);});})},async runHooks(t,e,o){let r=await this.findHooks(t,e),n=e.startsWith("pre-");for(let i of r)if(!await this.executeHook(i,o,t)&&n)return false;return true},async runHooksForContext(t,e,o,r){return !(!await this.runHooks(t,o,r)||e&&!await this.runHooks(e,o,r))}},E=fo;});var ie,ae=f(()=>{k();G();v();$();ie=p({options:z$1.object({target:z$1.enum(c.targets).optional().describe("Target level")}),args:z$1.object({type:z$1.enum(c.hookTypes).describe("Hook type to run")}),handler:async({type:t,target:e})=>{let{targetDir:o,entityType:r}=j.getTargetDir(e),n={action:t,entityType:r,project:j.getProjectFromPwd()||void 0,task:j.getTaskFromPwd()||void 0};await E.runHooks(o,t,n)||(console.error(`Hook ${t} failed`),process.exit(1)),console.log(`Hook ${t} completed successfully`);}});});var go,A,z=f(()=>{$();v();I();b();go={formatLogEntry(t,e){let o=new Date().toISOString().replace("T"," ").replace(/\.\d{3}Z$/,""),r=e?` | ${e}`:"";return `[${o}${r}] ${t}
474
- `},async appendStatus(t,e,o){let r=s.join(t,c.files.STATUS),n=this.formatLogEntry(e,o);await s.write(r,n);},async appendStatusIfExists(t,e,o){let r=s.join(t,c.files.STATUS);if(!await s.fileExists(r))return false;let i=this.formatLogEntry(e,o);return await s.write(r,i),true},async readStatus(t){let e=s.join(t,c.files.STATUS);return await s.fileExists(e)?await s.read(e):""},getCurrentAgent(){return process.env.CURRENT_AGENT},async logTask(t,e){let o=j.getCurrentContext();if(!o.project||!o.task)throw new Error("Not in a task directory");let r=s.join(y.AIP_HOME,c.dirs.PROJECTS,o.project,c.dirs.TASKS,o.task);await this.appendStatus(r,t,e||this.getCurrentAgent());},async logProject(t,e){let o=j.getProjectFromPwd();if(!o)throw new Error("Not in a project directory");let r=s.join(y.AIP_HOME,c.dirs.PROJECTS,o);await this.appendStatus(r,t,e||this.getCurrentAgent());},async logStatusChange(t,e,o,r){let n=e;if(o&&Object.keys(o).length>0){let i=Object.entries(o).map(([a,d])=>`${a}=${d}`).join(", ");n=`${e}: ${i}`;}await this.appendStatus(t,n,r);}},A=go;});var ce,pe=f(()=>{k();G();b();x();z();ce=p({description:"Create a new project with name, description, optional status and assignee",options:z$1.object({description:z$1.string().describe("Project description"),status:z$1.string().default("active").describe("Initial status"),assignee:z$1.string().optional().describe("Assignee agent slug"),summary:z$1.string().optional().describe("Override the default summary line to append to status.md")}),args:z$1.object({name:z$1.string().describe("Project name")}),handler:async({name:t,description:e,status:o,assignee:r,summary:n})=>{let i=s.slugify(t),a=m.getProjectDir(i);if(!await E.runHooks(a,"pre-create",{action:"pre-create",entityType:"project"}))throw new Error("Pre-create hook failed, aborting project creation");await m.createProject(i,{name:t,description:e,status:o,assignee:r,created:new Date().toISOString()}),await A.appendStatus(a,n||`Project created: ${t} > status is ${o}`),await E.runHooks(a,"post-create",{action:"post-create",entityType:"project"}),console.log(`Project created: ${i}`),console.log(` Path: ${a}`);}});});var le,me=f(()=>{k();v();le=p({options:z$1.object({}),handler:async()=>{let t=j.getProjectFromPwd();t||(console.error("Not in a project directory"),process.exit(1)),console.log(t);}});});var ue,fe=f(()=>{k();x();ue=p({description:"List all projects, optionally filtered by status",options:z$1.object({status:z$1.string().optional().describe("Filter by status")}),handler:async({status:t})=>{let e=await m.listProjects(),o=[];for(let r of e){let n=await m.getProject(r);n&&(t&&n.status!==t||o.push({slug:r,name:n.name||r,status:n.status,assignee:n.assignee}));}if(o.length===0){console.log("No projects found");return}console.log("Projects:"),console.log("---");for(let r of o)console.log(`${r.slug.padEnd(20)} ${r.name?.padEnd(30)||""} ${r.status||""} ${r.assignee||""}`);}});});var ge,ke=f(()=>{k();x();ge=p({description:"Output project directory path (for cd)",options:z$1.object({}),args:z$1.object({name:z$1.string().describe("Project name (slug)")}),handler:async({name:t})=>{let e=m.getProjectDir(t);console.log(e);}});});var he,ye=f(()=>{k();x();G();z();v();he=p({description:"Update project properties: name, description, status, assignee, or append summary",options:z$1.object({name:z$1.string().optional().describe("New name"),description:z$1.string().optional().describe("New description"),status:z$1.string().optional().describe("New status"),assignee:z$1.string().optional().describe("New assignee"),summary:z$1.string().optional().describe("Optional summary to append to status.md")}),args:z$1.object({project:z$1.string().optional().describe("Project slug (defaults to current project from $PWD)")}),handler:async({project:t,name:e,description:o,status:r,assignee:n,summary:i})=>{let a=t||j.getProjectFromPwd();if(!a)throw new Error("No project specified and not in a project directory");let d=m.getProjectDir(a);if(!await E.runHooks(d,"pre-update",{action:"pre-update",entityType:"project"}))throw new Error("Pre-update hook failed, aborting update");let l={};if(e&&(l.name=e),o&&(l.description=o),r&&(l.status=r),n&&(l.assignee=n),Object.keys(l).length===0){console.log("No updates provided");return}await m.updateProject(a,l);let g=Object.entries(l).map(([P,O])=>`${P}=${O}`).join(", ");await A.appendStatus(d,`Updated: ${g}`),i&&await A.appendStatus(d,i),await E.runHooks(d,"post-update",{action:"post-update",entityType:"project"}),console.log(`Project ${a} updated`);}});});var je,Te=f(()=>{$();k();I();b();je=p({description:"Read a skill's SKILL.md file into the console for agent context",options:z$1.object({}),args:z$1.object({name:z$1.string().describe("Skill name (directory name)")}),handler:async({name:t})=>{let e=s.join(y.AIP_HOME,c.dirs.SKILLS,t),o=s.join(e,c.files.SKILL);if(!await s.fileExists(o))throw new Error(`Skill not found: ${t}
475
- Expected at: ${o}`);await s.logFiles(o);}});});var we,Pe=f(()=>{k();G();b();x();z();we=p({description:"Create a new task with assignee and initial status",options:z$1.object({description:z$1.string().optional().describe("Task description"),assignee:z$1.string().optional().describe("Assignee agent slug"),status:z$1.string().default("backlog").describe("Initial status"),summary:z$1.string().optional().describe("Override the default summary line to append to status.md")}),args:z$1.object({project:z$1.string().describe("Project slug"),name:z$1.string().describe("Task name")}),handler:async({project:t,name:e,description:o,assignee:r,status:n,summary:i})=>{let a=s.slugify(e),d=m.getProjectDir(t),u=m.getTaskDir(t,a);if(!await E.runHooksForContext(d,u,"pre-create",{action:"pre-create",entityType:"task",project:t}))throw new Error("Pre-create hook failed, aborting task creation");await m.createTask(t,a,{name:e,description:o,assignee:r,status:n,created:new Date().toISOString()}),await A.appendStatus(u,i||`Created: ${e}`),await A.appendStatus(d,`Task created: ${a} > status is ${n}`),await E.runHooksForContext(d,u,"post-create",{action:"post-create",entityType:"task",project:t}),console.log(`Task created: ${a}`),console.log(` Project: ${t}`),console.log(` Path: ${u}`);}});});var be,Se=f(()=>{k();v();be=p({description:"Get the current task slug from PWD",options:z$1.object({}),handler:async()=>{let t=j.getTaskFromPwd();t||(console.error("Not in a task directory"),process.exit(1)),console.log(t);}});});var xe,Ee=f(()=>{v();k();x();xe=p({description:"Output full task context (main.md, status.md) for ingestion by agents",options:z$1.object({project:z$1.string().optional().describe("Project slug (searches all projects if not provided)")}),args:z$1.object({task:z$1.string().optional().describe("Task slug (default: from $PWD)")}),handler:async({project:t,task:e})=>{let o=j.getCurrentContext(),r=e??o.task;if(!r)throw new Error("Need task slug (or cd into task dir)");let{project:n}=await m.findTask(r,t);await m.ingestTask(n,r);}});});var Ae,$e=f(()=>{k();x();Ae=p({description:"List tasks, optionally filtered by project, status, assignee, or search query",options:z$1.object({project:z$1.string().optional().describe("Project slug (searches all projects if not provided)"),statuses:z$1.array(z$1.string()).default([]).describe("Filter by statuses (multiple allowed)"),assignee:z$1.string().optional().describe("Filter by assignee"),all:z$1.boolean().default(false).describe("Include all tasks (including done/blocked)"),search:z$1.string().optional().describe("Search query (matches task slug or name, case-insensitive)")}),handler:async({project:t,statuses:e,assignee:o,all:r,search:n})=>{if(e&&e.length>0){for(let l of e)if(!X.includes(l))throw new Error(`Invalid status: ${l}. Valid values: ${X.join(", ")}`)}let i;e&&e.length>0?i=e:r?i=X:i=At;let a=t?[t]:await m.listProjects(),d={};for(let l of a){let g=await m.listTasks(l),P=[];for(let O of g){let h=await m.getTask(l,O);if(h&&!(i.length>0&&!i.includes(h.status||""))&&!(o&&h.assignee!==o)){if(n){let H=n.toLowerCase(),lt=O.toLowerCase().includes(H),mt=(h.name||"").toLowerCase().includes(H);if(!lt&&!mt)continue}P.push({slug:O,name:h.name||O,status:h.status,assignee:h.assignee});}}P.length>0&&(d[l]=P.sort((O,h)=>O.slug.localeCompare(h.slug)));}let u=Object.keys(d).sort();if(u.length===0){console.log("No tasks found");return}for(let l of u){console.log(`
476
- ${l}:`),console.log("---");for(let g of d[l])console.log(`${g.slug.padEnd(20)} ${g.name?.padEnd(30)||""} ${g.status||""} ${g.assignee||""}`);}}});});var ve,Oe=f(()=>{k();x();ve=p({description:"Output task directory path (for cd)",options:z$1.object({project:z$1.string().optional().describe("Project slug (searches all projects if not provided)")}),args:z$1.object({task:z$1.string().describe("Task slug")}),handler:async({project:t,task:e})=>{let{project:o,task:r}=await m.findTask(e,t),n=m.getTaskDir(o,r);console.log(n);}});});var at,wt=f(()=>{v();k();G();x();z();at=p({description:"Update task properties: name, description, status, assignee, or append summary",options:z$1.object({name:z$1.string().optional().describe("New name"),description:z$1.string().optional().describe("New description"),status:z$1.string().optional().describe("New status"),assignee:z$1.string().optional().describe("New assignee"),project:z$1.string().optional().describe("Project slug (searches all projects if not provided)"),summary:z$1.string().optional().describe("Override the default summary line to append to status.md")}),args:z$1.object({task:z$1.string().optional().describe("Task slug (default: from $PWD)")}),handler:async({project:t,task:e,name:o,description:r,status:n,assignee:i,summary:a})=>{let d=j.getCurrentContext(),u=e??d.task;if(!u)throw new Error("No task specified (use --task or cd into task dir)");let{project:l}=await m.findTask(u,t),g=m.getTaskDir(l,u),P=m.getProjectDir(l);if(!await E.runHooksForContext(P,g,"pre-update",{action:"pre-update",entityType:"task",project:l,task:u}))throw new Error("Pre-update hook failed, aborting update");let h={};if(o&&(h.name=o),r&&(h.description=r),n&&(h.status=n),i&&(h.assignee=i),Object.keys(h).length===0&&!a){console.log("No updates provided");return}if(Object.keys(h).length>0){await m.updateTask(l,u,h);let lt=Object.entries(h).map(([mt,Le])=>`${mt}=${Le}`).join(", ");await A.appendStatus(g,`Updated: ${lt}`);}let H=a;!a&&(h.status||h.assignee)&&(H=`Updated: ${h.status?` status to ${h.status}`:""}${h.assignee?` assignee to ${h.assignee}`:""}`),H&&await A.appendStatus(g,H),h.status&&await A.appendStatus(P,`Task updated: ${u} > status to ${h.status}`),await E.runHooksForContext(m.getProjectDir(l),g,"post-update",{action:"post-update",entityType:"task",project:l,task:u}),console.log(`Task ${u} updated`);}});});var De,Ce=f(()=>{v();k();x();wt();De=p({description:"Start a task: set status to in-progress, optionally print context",options:z$1.object({project:z$1.string().optional().describe("Project slug (searches all projects if not provided)"),ingest:z$1.boolean().default(false).describe("Also output context for this task")}),args:z$1.object({task:z$1.string().optional().describe("Task slug (default: from $PWD)")}),handler:async({project:t,task:e,ingest:o})=>{let r=j.getCurrentContext(),n=e??r.task;if(!n)throw new Error("No task specified (use --task or cd into task dir)");let{project:i}=await m.findTask(n,t);(await m.getTask(i,n))?.status!=="in-progress"&&await at.handler({project:i,task:n,status:"in-progress"}),o&&await m.ingestTask(i,n);}});});var Ie,Ne=f(()=>{k();x();z();Ie=p({description:"Post-mortem analysis for a completed task",options:z$1.object({}),args:z$1.object({project:z$1.string().describe("Project slug"),task:z$1.string().describe("Task slug")}),handler:async({project:t,task:e})=>{let o=m.getTaskDir(t,e),r=await m.getTask(t,e),i=(await A.readStatus(o)).split(`
477
- `).filter(u=>u.startsWith("[")).length,a=[],d=r?.name||e;i>5&&a.push("High status update count - consider breaking into smaller tasks"),d.toLowerCase().includes("implement")&&a.push("Implementation task - check if similar patterns exist to reuse"),d.toLowerCase().includes("create")&&d.toLowerCase().includes("command")&&a.push("Command creation - check existing command patterns in src/commands/"),console.log(`
478
- === Post-Mortem Analysis ===`),console.log(`Project: ${t}`),console.log(`Task: ${e}`),console.log(`Name: ${d}`),console.log(`Status: ${r?.status||"unknown"}`),console.log(`Status updates: ${i}`),a.length>0?(console.log(`
479
- Suggestions:`),a.forEach(u=>console.log(` - ${u}`))):console.log(`
390
+ `;else throw new Error(`Unsupported language: ${r}`);await n.write(m,k);let{chmod:P}=await import('fs/promises');await P(m,493),console.log(`Hook created: ${m}`);}});});var To,v,z=f(()=>{$();T();To={async findHooks(t,e){let o=n.join(t,c.dirs.HOOKS);if(!await n.fileExists(o))return [];let s=await n.listDir(o),i=`${e}.`;return s.filter(a=>a.startsWith(i)).map(a=>n.join(o,a))},async executeHook(t,e,o){if(!await n.fileExists(t))return true;let s=e.project?n.joinHome(c.dirs.PROJECTS,e.project):o,i=e.task?n.join(s,c.dirs.TASKS,e.task):"",a={...process.env,HOOK_TYPE:e.action,ENTITY_TYPE:e.entityType,TARGET_DIR:o,PROJECT_DIR:s,...e.project?{PROJECT_SLUG:e.project}:{},...e.task?{TASK_SLUG:e.task,TASK_DIR:i}:{}};return new Promise(l=>{let m=spawn(t,[],{stdio:"inherit",env:a,cwd:F.dirname(t),shell:false});m.on("close",(d,k)=>{d===0?l(true):(console.error(`Hook ${F.basename(t)} failed (code=${d??k})`),l(false));}),m.on("error",d=>{console.error(`Failed to execute hook ${t}: ${d.message}`),l(false);});})},async runHooks(t,e,o){let r=await this.findHooks(t,e),s=e.startsWith("pre-");for(let i of r)if(!await this.executeHook(i,o,t)&&s)return false;return true},async runHooksForContext(t,e,o,r){return !(!await this.runHooks(t,o,r)||e&&!await this.runHooks(e,o,r))}},v=To;});var re,se=f(()=>{g();z();D();$();re=p({options:z$1.object({target:z$1.enum(c.targets).optional().describe("Target level")}),args:z$1.object({type:z$1.enum(c.hookTypes).describe("Hook type to run")}),handler:async({type:t,target:e})=>{let{targetDir:o,entityType:r}=h.getTargetDir(e),s={action:t,entityType:r,project:h.getProjectFromPwd()||void 0,task:h.getTaskFromPwd()||void 0};await v.runHooks(o,t,s)||(console.error(`Hook ${t} failed`),process.exit(1)),console.log(`Hook ${t} completed successfully`);}});});var wo,w,C=f(()=>{$();D();T();wo={formatEntry(t,e,o,r){let s=new Date,i=s.toISOString().split("T")[0],a=s.toLocaleTimeString("en-US",{hour12:false,hour:"2-digit",minute:"2-digit",second:"2-digit"});return `${i} ${a} ${t} ${e} ${o} ${r}
391
+ `},async appendStatus(t,e,o,r,s){let i=n.join(t,c.files.STATUS),a=this.formatEntry(e,o,r,s);await n.append(i,a);},async appendStatusIfExists(t,e,o,r,s){let i=n.join(t,c.files.STATUS);if(!await n.fileExists(i))return false;let l=this.formatEntry(e,o,r,s);return await n.append(i,l),true},async readStatus(t){let e=n.join(t,c.files.STATUS);return await n.fileExists(e)?await n.read(e):""},getCurrentAgent(){return process.env.CURRENT_AGENT},async logTask(t,e,o){let r=h.getCurrentContext();if(!r.project||!r.task)throw new Error("Not in a task directory");let s=n.joinHome(c.dirs.PROJECTS,r.project,c.dirs.TASKS,r.task);await this.appendStatus(s,"task",t,"log",o?`${o}: ${e}`:e);},async logProject(t,e,o){let r=h.getProjectFromPwd();if(!r)throw new Error("Not in a project directory");let s=n.joinHome(c.dirs.PROJECTS,r);await this.appendStatus(s,"project",t,"log",o?`${o}: ${e}`:e);},async logStatusChange(t,e,o,r,s,i){let a=r;if(s&&Object.keys(s).length>0){let l=Object.entries(s).map(([m,d])=>`${m}=${d}`).join(", ");a=`${r}: ${l}`;}await this.appendStatus(t,e,o,"updated",i?`${i} | ${a}`:a);}},w=wo;});var ne,ie=f(()=>{g();D();T();C();$();ne=p({description:"Append a custom entry to status.tsv",options:z$1.object({project:z$1.string().optional().describe("Project slug (uses current project from $PWD if not provided)"),task:z$1.string().optional().describe("Task slug (uses current task from $PWD if not provided)")}),args:z$1.object({text:z$1.string().describe("Text to append")}),handler:async({project:t,task:e,text:o})=>{let r=h.getCurrentContext(),s=t||r.project;if(!s)throw new Error("No project specified. Use --project or run from a project/task directory");let i=n.joinHome(c.dirs.PROJECTS,s);if(e||r.task){let a=e||r.task;if(!a)throw new Error("No task specified");let l=n.join(i,c.dirs.TASKS,a);await w.appendStatus(l,"task",a,"log",o),console.log(`Appended to task ${a} status.tsv`);}else await w.appendStatus(i,"project",s,"log",o),console.log(`Appended to project ${s} status.tsv`);}});});var ae,ce=f(()=>{g();D();T();C();$();ae=p({description:"Read status.tsv history",options:z$1.object({project:z$1.string().optional().describe("Project slug (uses current project from $PWD if not provided)"),task:z$1.string().optional().describe("Task slug (uses current task from $PWD if not provided)")}),args:z$1.object({}),handler:async({project:t,task:e})=>{let o=h.getCurrentContext(),r=t||o.project;if(!r)throw new Error("No project specified. Use --project or run from a project/task directory");let s=n.joinHome(c.dirs.PROJECTS,r);if(e||o.task){let i=e||o.task;if(!i)throw new Error("No task specified");let a=n.join(s,c.dirs.TASKS,i),l=await w.readStatus(a);console.log(l||`No status.tsv found for task ${i}`);}else {let i=await w.readStatus(s);console.log(i||`No status.tsv found for project ${r}`);}}});});var pe,le=f(()=>{g();z();T();x();C();pe=p({description:"Create a new project with name, description, optional status and assignee",options:z$1.object({description:z$1.string().describe("Project description"),status:z$1.string().default("active").describe("Initial status"),assignee:z$1.string().optional().describe("Assignee agent slug")}),args:z$1.object({name:z$1.string().describe("Project name")}),handler:async({name:t,description:e,status:o,assignee:r})=>{let s=n.slugify(t),i=u.getProjectDir(s);if(!await v.runHooks(i,"pre-create",{action:"pre-create",entityType:"project"}))throw new Error("Pre-create hook failed, aborting project creation");await u.createProject(s,{name:t,description:e,status:o,assignee:r,created:new Date().toISOString()}),await w.appendStatus(i,"project",s,"created",`status is ${o}`),await v.runHooks(i,"post-create",{action:"post-create",entityType:"project"}),console.log(`Project created: ${s}`),console.log(` Path: ${i}`);}});});var me,de=f(()=>{g();D();me=p({options:z$1.object({}),handler:async()=>{let t=h.getProjectFromPwd();t||(console.error("Not in a project directory"),process.exit(1)),console.log(t);}});});var fe,ge=f(()=>{g();x();fe=p({description:"List all projects, optionally filtered by status",options:z$1.object({status:z$1.string().optional().describe("Filter by status")}),handler:async({status:t})=>{let e=await u.listProjects(),o=[];for(let r of e){let s=await u.getProject(r);s&&(t&&s.status!==t||o.push({slug:r,name:s.name||r,status:s.status,assignee:s.assignee}));}if(o.length===0){console.log("No projects found");return}console.log("Projects:"),console.log("---");for(let r of o)console.log(`${r.slug.padEnd(20)} ${r.name?.padEnd(30)||""} ${r.status||""} ${r.assignee||""}`);}});});var ke,he=f(()=>{g();x();ke=p({description:"Output project directory path (for cd)",options:z$1.object({}),args:z$1.object({name:z$1.string().describe("Project name (slug)")}),handler:async({name:t})=>{let e=u.getProjectDir(t);console.log(e);}});});var je,ye=f(()=>{g();x();z();C();D();je=p({description:"Update project properties: name, description, status, assignee",options:z$1.object({name:z$1.string().optional().describe("New name"),description:z$1.string().optional().describe("New description"),status:z$1.string().optional().describe("New status"),assignee:z$1.string().optional().describe("New assignee")}),args:z$1.object({project:z$1.string().optional().describe("Project slug (defaults to current project from $PWD)")}),handler:async({project:t,name:e,description:o,status:r,assignee:s})=>{let i=t||h.getProjectFromPwd();if(!i)throw new Error("No project specified and not in a project directory");let a=u.getProjectDir(i);if(!await v.runHooks(a,"pre-update",{action:"pre-update",entityType:"project"}))throw new Error("Pre-update hook failed, aborting update");let m={};if(e&&(m.name=e),o&&(m.description=o),r&&(m.status=r),s&&(m.assignee=s),Object.keys(m).length===0){console.log("No updates provided");return}await u.updateProject(i,m);let d=Object.entries(m).map(([k,P])=>`${k}=${P}`).join(", ");await w.appendStatus(a,"project",i,"updated",d),await v.runHooks(a,"post-update",{action:"post-update",entityType:"project"}),console.log(`Project ${i} updated`);}});});var Te,we=f(()=>{$();g();H();T();Te=p({description:"Read a skill's SKILL.md file into the console for agent context",options:z$1.object({}),args:z$1.object({name:z$1.string().describe("Skill name (directory name)")}),handler:async({name:t})=>{let e=n.join(E.AIP_HOME,c.dirs.SKILLS,t),o=n.join(e,c.files.SKILL);if(!await n.fileExists(o))throw new Error(`Skill not found: ${t}
392
+ Expected at: ${o}`);await n.logFiles(o);}});});var Se,be=f(()=>{g();z();T();x();C();Se=p({description:"Create a new task with assignee and initial status",options:z$1.object({description:z$1.string().optional().describe("Task description"),assignee:z$1.string().optional().describe("Assignee agent slug"),status:z$1.string().default("backlog").describe("Initial status")}),args:z$1.object({project:z$1.string().describe("Project slug"),name:z$1.string().describe("Task name")}),handler:async({project:t,name:e,description:o,assignee:r,status:s})=>{let i=n.slugify(e),a=u.getProjectDir(t),l=u.getTaskDir(t,i);if(!await v.runHooksForContext(a,l,"pre-create",{action:"pre-create",entityType:"task",project:t}))throw new Error("Pre-create hook failed, aborting task creation");await u.createTask(t,i,{name:e,description:o,assignee:r,status:s,created:new Date().toISOString()}),await w.appendStatus(l,"task",i,"created",e),await w.appendStatus(a,"task",i,"created",`status is ${s}`),await v.runHooksForContext(a,l,"post-create",{action:"post-create",entityType:"task",project:t}),console.log(`Task created: ${i}`),console.log(` Project: ${t}`),console.log(` Path: ${l}`);}});});var Pe,xe=f(()=>{g();D();Pe=p({description:"Get the current task slug from PWD",options:z$1.object({}),handler:async()=>{let t=h.getTaskFromPwd();t||(console.error("Not in a task directory"),process.exit(1)),console.log(t);}});});var $e,ve=f(()=>{D();g();x();$e=p({description:"Output full task context (main.md, status.tsv) for ingestion by agents",options:z$1.object({project:z$1.string().optional().describe("Project slug (searches all projects if not provided)")}),args:z$1.object({task:z$1.string().optional().describe("Task slug (default: from $PWD)")}),handler:async({project:t,task:e})=>{let o=h.getCurrentContext(),r=e??o.task;if(!r)throw new Error("Need task slug (or cd into task dir)");let{project:s}=await u.findTask(r,t);await u.ingestTask(s,r);}});});var Ee,Ae=f(()=>{g();x();Ee=p({description:"List tasks, optionally filtered by project, status, assignee, or search query",options:z$1.object({project:z$1.string().optional().describe("Project slug (searches all projects if not provided)"),statuses:z$1.array(z$1.string()).default([]).describe("Filter by statuses (multiple allowed)"),assignee:z$1.string().optional().describe("Filter by assignee"),all:z$1.boolean().default(false).describe("Include all tasks (including done/blocked)"),search:z$1.string().optional().describe("Search query (matches task slug or name, case-insensitive)")}),handler:async({project:t,statuses:e,assignee:o,all:r,search:s})=>{if(e&&e.length>0){for(let d of e)if(!et.includes(d))throw new Error(`Invalid status: ${d}. Valid values: ${et.join(", ")}`)}let i;e&&e.length>0?i=e:r?i=et:i=vt;let a=t?[t]:await u.listProjects(),l={};for(let d of a){let k=await u.listTasks(d),P=[];for(let S of k){let O=await u.getTask(d,S);if(O&&!(i.length>0&&!i.includes(O.status||""))&&!(o&&O.assignee!==o)){if(s){let tt=s.toLowerCase(),mt=S.toLowerCase().includes(tt),Fe=(O.name||"").toLowerCase().includes(tt);if(!mt&&!Fe)continue}P.push({slug:S,name:O.name||S,status:O.status,assignee:O.assignee});}}P.length>0&&(l[d]=P.sort((S,O)=>S.slug.localeCompare(O.slug)));}let m=Object.keys(l).sort();if(m.length===0){console.log("No tasks found");return}for(let d of m){console.log(`
393
+ ${d}:`),console.log("---");for(let k of l[d])console.log(`${k.slug.padEnd(20)} ${k.name?.padEnd(30)||""} ${k.status||""} ${k.assignee||""}`);}}});});var De,Oe=f(()=>{g();x();De=p({description:"Output task directory path (for cd)",options:z$1.object({project:z$1.string().optional().describe("Project slug (searches all projects if not provided)")}),args:z$1.object({task:z$1.string().describe("Task slug")}),handler:async({project:t,task:e})=>{let{project:o,task:r}=await u.findTask(e,t),s=u.getTaskDir(o,r);console.log(s);}});});var ct,St=f(()=>{D();g();z();x();C();ct=p({description:"Update task properties: name, description, status, assignee",options:z$1.object({name:z$1.string().optional().describe("New name"),description:z$1.string().optional().describe("New description"),status:z$1.string().optional().describe("New status"),assignee:z$1.string().optional().describe("New assignee"),project:z$1.string().optional().describe("Project slug (searches all projects if not provided)")}),args:z$1.object({task:z$1.string().optional().describe("Task slug (default: from $PWD)")}),handler:async({project:t,task:e,name:o,description:r,status:s,assignee:i})=>{let a=h.getCurrentContext(),l=e??a.task;if(!l)throw new Error("No task specified (use --task or cd into task dir)");let{project:m}=await u.findTask(l,t),d=u.getTaskDir(m,l),k=u.getProjectDir(m);if(!await v.runHooksForContext(k,d,"pre-update",{action:"pre-update",entityType:"task",project:m,task:l}))throw new Error("Pre-update hook failed, aborting update");let S={};if(o&&(S.name=o),r&&(S.description=r),s&&(S.status=s),i&&(S.assignee=i),Object.keys(S).length===0){console.log("No updates provided");return}if(Object.keys(S).length>0){await u.updateTask(m,l,S);let O=Object.entries(S).map(([tt,mt])=>`${tt}=${mt}`).join(", ");await w.appendStatus(d,"task",l,"updated",O);}S.status&&await w.appendStatus(k,"task",l,"updated",`status to ${S.status}`),await v.runHooksForContext(u.getProjectDir(m),d,"post-update",{action:"post-update",entityType:"task",project:m,task:l}),console.log(`Task ${l} updated`);}});});var Ce,Re=f(()=>{D();g();x();St();Ce=p({description:"Start a task: set status to in-progress, optionally print context",options:z$1.object({project:z$1.string().optional().describe("Project slug (searches all projects if not provided)"),ingest:z$1.boolean().default(false).describe("Also output context for this task")}),args:z$1.object({task:z$1.string().optional().describe("Task slug (default: from $PWD)")}),handler:async({project:t,task:e,ingest:o})=>{let r=h.getCurrentContext(),s=e??r.task;if(!s)throw new Error("No task specified (use --task or cd into task dir)");let{project:i}=await u.findTask(s,t);(await u.getTask(i,s))?.status!=="in-progress"&&await ct.handler({project:i,task:s,status:"in-progress"}),o&&await u.ingestTask(i,s);}});});var Ne,Ie=f(()=>{g();x();C();Ne=p({description:"Post-mortem analysis for a completed task",options:z$1.object({}),args:z$1.object({project:z$1.string().describe("Project slug"),task:z$1.string().describe("Task slug")}),handler:async({project:t,task:e})=>{let o=u.getTaskDir(t,e),r=await u.getTask(t,e),i=(await w.readStatus(o)).split(`
394
+ `).filter(m=>m.startsWith("[")).length,a=[],l=r?.name||e;i>5&&a.push("High status update count - consider breaking into smaller tasks"),l.toLowerCase().includes("implement")&&a.push("Implementation task - check if similar patterns exist to reuse"),l.toLowerCase().includes("create")&&l.toLowerCase().includes("command")&&a.push("Command creation - check existing command patterns in src/commands/"),console.log(`
395
+ === Post-Mortem Analysis ===`),console.log(`Project: ${t}`),console.log(`Task: ${e}`),console.log(`Name: ${l}`),console.log(`Status: ${r?.status||"unknown"}`),console.log(`Status updates: ${i}`),a.length>0?(console.log(`
396
+ Suggestions:`),a.forEach(m=>console.log(` - ${m}`))):console.log(`
480
397
  No specific suggestions - task looks well-scoped`),console.log(`
481
398
  === End Post-Mortem ===
482
- `);}});});var Re,Ue=f(()=>{k();b();Re=p({description:"Read one or more files into the console",options:z$1.object({}),args:z$1.object({paths:z$1.array(z$1.string()).describe("File paths to read")}),handler:async({paths:t})=>{await s.logFiles(...t);}});});var gt={};He(gt,{default:()=>F});var yo,F,tt=f(()=>{Ot();Ct();Nt();Ut();Lt();Kt();zt();Jt();te();oe();se();ae();pe();me();fe();ke();ye();Te();Pe();Se();Ee();$e();Oe();Ce();wt();Ne();Ue();yo={agent:{create:vt,current:Dt,list:It,path:Rt,start:_t},help:{api:Mt,hooks:Gt,quickstart:Wt,skill:Xt,usage:ee},hook:{create:re,run:ie},project:{create:ce,current:le,list:ue,path:ge,update:he},skill:{read:je},task:{create:we,current:be,ingest:xe,list:Ae,path:ve,start:De,update:at},util:{postmortem:Ie,read:Re}},F=yo;});W();tt();b();process.on("unhandledRejection",t=>{console.error("Unhandled Rejection:",t),process.exit(1);});process.on("uncaughtException",t=>{console.error("Unhandled Exception:",t),process.exit(1);});async function _e(t){let[e,o,...r]=t;(e==="--version"||e==="-v")&&(console.log(S.version),process.exit(0));try{(!e||!s.isKeyOf(e,F))&&(await F.help.usage.handler({}),process.exit(1));let n=F[e];(!o||!s.isKeyOf(o,n))&&(await F.help.usage.handler({name:e}),process.exit(1));let i=n[o];i||(console.error(`Error: unknown command '${e} ${o}'`),console.log("Run with --help for more information"),process.exit(1)),await i.handler(i.parser.name(`${e} ${o}`).parse(r));}catch(n){console.error("Error:",s.errorMessage(n)),process.exit(1);}}var ui=_e,fi=F;s.isMain()&&_e(process.argv.slice(2));export{fi as commands,ui as default};
399
+ `);}});});var Ue,_e=f(()=>{g();T();Ue=p({description:"Read one or more files into the console",options:z$1.object({}),args:z$1.object({paths:z$1.array(z$1.string()).describe("File paths to read")}),handler:async({paths:t})=>{await n.logFiles(...t);}});});var kt={};Ke(kt,{default:()=>L});var Po,L,ot=f(()=>{Dt();Ct();Nt();Ut();Lt();Mt();zt();Bt();Yt();Xt();ee();se();ie();ce();le();de();ge();he();ye();we();be();xe();ve();Ae();Oe();Re();St();Ie();_e();Po={agent:{create:At,current:Ot,list:Rt,path:It,start:_t},help:{api:Kt,hooks:Gt,quickstart:Jt,skill:qt,usage:Qt},hook:{create:te,run:re},log:{append:ne,read:ae},project:{create:pe,current:me,list:fe,path:ke,update:je},skill:{read:Te},task:{create:Se,current:Pe,ingest:$e,list:Ee,path:De,start:Ce,update:ct},util:{postmortem:Ne,read:Ue}},L=Po;});B();ot();T();process.on("unhandledRejection",t=>{console.error("Unhandled Rejection:",t),process.exit(1);});process.on("uncaughtException",t=>{console.error("Unhandled Exception:",t),process.exit(1);});async function Le(t){let[e,o,...r]=t;(e==="--version"||e==="-v")&&(console.log(b.version),process.exit(0));try{(!e||!n.isKeyOf(e,L))&&(await L.help.usage.handler({}),process.exit(1));let s=L[e];(!o||!n.isKeyOf(o,s))&&(await L.help.usage.handler({name:e}),process.exit(1));let i=s[o];i||(console.error(`Error: unknown command '${e} ${o}'`),console.log("Run with --help for more information"),process.exit(1)),await i.handler(i.parser.name(`${e} ${o}`).parse(r));}catch(s){console.error("Error:",n.errorMessage(s)),process.exit(1);}}var Ri=Le,Ni=L;n.isMain()&&Le(process.argv.slice(2));export{Ni as commands,Ri as default};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-projects",
3
- "version": "1.4.0",
3
+ "version": "1.5.1",
4
4
  "type": "module",
5
5
  "description": "Useful CLI for AI agents to create and manage projects, tasks, skills and agents",
6
6
  "main": "dist/index.js",
@@ -46,7 +46,8 @@
46
46
  "publish:dry": "npm pack --dry-run",
47
47
  "version:patch": "npm version patch",
48
48
  "version:minor": "npm version minor",
49
- "version:major": "npm version major"
49
+ "version:major": "npm version major",
50
+ "agent:stop": "npm run -s lint:full:silent"
50
51
  },
51
52
  "keywords": [
52
53
  "ai",