jig-dev 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -324,7 +324,7 @@ ${i.join(`
|
|
|
324
324
|
`),h=Hd(f,"Intent")||Hd(f,"Purpose")||"",m=eL(f,"Acceptance Criteria"),g=eL(f,"Constraints"),y=Hd(f,"Architecture")||"",v=Hd(f,"Key Files")||"",b={spec_name:i.name,layer:i.layer||"unknown",intent:h,architecture:y,key_files:v,acceptance_criteria:m,constraints:g,context_bundles:u.map(w=>({name:w.name,description:w.description,files:w.files,constraints:w.constraints,patterns:w.patterns})),existing_tasks:d,instructions:"Analyze this spec and create tasks using the create_task tool. Each task needs: name (kebab-case), objective, intent, acceptance_criteria, file_scope, verification (with behavioral checks), and dependencies. Do NOT call decompose again \u2014 use create_task for each task you propose."};return a&&(b.full_spec_content=a),JSON.stringify(b,null,2)}async fileFinding(e,r,n,s){let i=s??await this.resolveDefaultProjectId();if(!i)return"No project found. Create a project first.";let o=n?`${e}
|
|
325
325
|
|
|
326
326
|
Context: ${n}`:e,{data:a,error:c}=await this.supabase.from("findings").insert({project_id:i,content:o,pile_type:r,status:"new"}).select("id").single();if(c)return`Failed to file ${r}: ${c.message}`;this.triggerTriage(i,a.id,o,r).catch(()=>{});let l=r==="bug"?"Bug":"Idea",u=n?"claude_ai":"human";return this.logContext("project",i,"observation",`New ${r} filed: ${e.slice(0,200)}`,u,i),`${l} filed. ID: ${a.id}`}async listFindings(e,r){let n=r??await this.resolveDefaultProjectId();if(!n)return"No project found.";let s=e?.limit??20,i=this.supabase.from("findings").select("id, content, pile_type, suggested_spec_id, suggested_severity, status, created_at").eq("project_id",n).order("created_at",{ascending:!1}).limit(s);e?.pileType&&(i=i.eq("pile_type",e.pileType)),e?.status?i=i.eq("status",e.status):i=i.neq("status","dismissed");let{data:o,error:a}=await i;if(a)return`Failed to list findings: ${a.message}`;if(!o||o.length===0)return"No findings.";let c=o.map(d=>d.suggested_spec_id).filter(d=>d!==null),l={};if(c.length>0){let{data:d}=await this.supabase.from("specs").select("id, name").in("id",[...new Set(c)]);for(let p of d||[])l[p.id]=p.name}return o.map(d=>{let p=d.suggested_spec_id?l[d.suggested_spec_id]||"unknown":null,f=[`[${d.pile_type}]`,d.content];return p&&f.push(`(spec: ${p})`),d.suggested_severity&&f.push(`(${d.suggested_severity})`),f.push(`[${d.status}]`),f.push(`id: ${d.id}`),f.join(" ")}).join(`
|
|
327
|
-
`)}async dismissFinding(e,r){let n=r??await this.resolveDefaultProjectId();if(!n)return"No project found. Create a project first.";let{error:s}=await this.supabase.from("findings").update({status:"dismissed",updated_at:new Date().toISOString()}).eq("id",e.trim()).eq("project_id",n);return s?`Failed to dismiss finding: ${s.message}`:"Finding dismissed."}async triggerTriage(e,r,n,s){try{let{triageFinding:i}=await Promise.resolve().then(()=>(YM(),GM));await i(this.supabase,e,r,n,s)}catch(i){console.error(`[triage] Failed to triage finding ${r}: ${i instanceof Error?i.message:String(i)}`)}}async showStatus(e,r){if(e)return await this.listTasks(e,r);let n=this.supabase.from("specs").select("id, name, status, parent_spec_id");r&&(n=n.eq("project_id",r)),n=n.neq("status","archived");let{data:s,error:i}=await n;if(i)throw new Error(`Failed to get status: ${i.message}`);if(!s||s.length===0)return"No specs found.";let o=s.map(g=>g.id),{data:a}=await this.supabase.from("tasks").select("spec_id, status").in("spec_id",o),c=new Map,l=new Map;for(let g of a||[]){let y=g.spec_id;c.set(y,(c.get(y)||0)+1),g.status==="passed"&&l.set(y,(l.get(y)||0)+1)}let u=[],d=new Map,p=new Map;for(let g of s)p.set(g.id,g);for(let g of s){let y=g.parent_spec_id;if(!y||!p.has(y))u.push(g);else{let v=d.get(y)||[];v.push(g),d.set(y,v)}}let f=(g,y)=>{let v=c.get(g.id)||0,b=l.get(g.id)||0,w=v>0?` (${b}/${v} tasks done)`:"";return`${y}[${g.status}] ${g.name}${w}`},h=["Project Status:",""];for(let g of u){h.push(f(g,""));let y=d.get(g.id)||[];for(let v of y)h.push(f(v," "))}let m=r||await this.resolveDefaultProjectId();if(m){let{data:g}=await this.supabase.from("findings").select("pile_type").eq("project_id",m).neq("status","dismissed");if(g&&g.length>0){let y=g.filter(w=>w.pile_type==="bug").length,v=g.filter(w=>w.pile_type==="idea").length,b=[];y>0&&b.push(`${y} bug${y===1?"":"s"}`),v>0&&b.push(`${v} idea${v===1?"":"s"}`),
|
|
327
|
+
`)}async dismissFinding(e,r){let n=r??await this.resolveDefaultProjectId();if(!n)return"No project found. Create a project first.";let{error:s}=await this.supabase.from("findings").update({status:"dismissed",updated_at:new Date().toISOString()}).eq("id",e.trim()).eq("project_id",n);return s?`Failed to dismiss finding: ${s.message}`:"Finding dismissed."}async triggerTriage(e,r,n,s){try{let{triageFinding:i}=await Promise.resolve().then(()=>(YM(),GM));await i(this.supabase,e,r,n,s)}catch(i){console.error(`[triage] Failed to triage finding ${r}: ${i instanceof Error?i.message:String(i)}`)}}async showStatus(e,r){if(e)return await this.listTasks(e,r);let n=this.supabase.from("specs").select("id, name, status, parent_spec_id");r&&(n=n.eq("project_id",r)),n=n.neq("status","archived");let{data:s,error:i}=await n;if(i)throw new Error(`Failed to get status: ${i.message}`);if(!s||s.length===0)return"No specs found.";let o=s.map(g=>g.id),{data:a}=await this.supabase.from("tasks").select("spec_id, status").in("spec_id",o),c=new Map,l=new Map;for(let g of a||[]){let y=g.spec_id;c.set(y,(c.get(y)||0)+1),g.status==="passed"&&l.set(y,(l.get(y)||0)+1)}let u=[],d=new Map,p=new Map;for(let g of s)p.set(g.id,g);for(let g of s){let y=g.parent_spec_id;if(!y||!p.has(y))u.push(g);else{let v=d.get(y)||[];v.push(g),d.set(y,v)}}let f=(g,y)=>{let v=c.get(g.id)||0,b=l.get(g.id)||0,w=v>0?` (${b}/${v} tasks done)`:"";return`${y}[${g.status}] ${g.name}${w}`},h=["Project Status:",""];for(let g of u){h.push(f(g,""));let y=d.get(g.id)||[];for(let v of y)h.push(f(v," "))}let m=r||await this.resolveDefaultProjectId();if(m){let{data:g}=await this.supabase.from("findings").select("id, pile_type, content, status").eq("project_id",m).neq("status","dismissed").order("created_at",{ascending:!1});if(g&&g.length>0){let y=g.filter(w=>w.pile_type==="bug").length,v=g.filter(w=>w.pile_type==="idea").length,b=[];y>0&&b.push(`${y} bug${y===1?"":"s"}`),v>0&&b.push(`${v} idea${v===1?"":"s"}`),h.push(""),h.push(`Findings: ${b.join(", ")}`);for(let w of g){let k=w.pile_type==="bug"?"bug":"idea",x=w.content.length>120?w.content.slice(0,117)+"...":w.content;h.push(` [${k}] ${x} [${w.status}] id: ${w.id.slice(0,8)}`)}}}return h.join(`
|
|
328
328
|
`)}async deleteSpec(e,r){let n=r||await this.resolveDefaultProjectId(),s=this.supabase.from("specs").select("id, name").eq("name",e);n&&(s=s.eq("project_id",n));let{data:i,error:o}=await s.limit(1).single();if(o||!i)return`Spec "${e}" not found.`;let a=i.id,{data:c}=await this.supabase.from("specs").select("name").eq("parent_spec_id",a);if(c&&c.length>0){let p=c.map(f=>f.name).join(", ");return`Cannot delete spec "${e}" because it has sub-specs: ${p}. Delete children first.`}let{data:l}=await this.supabase.from("tasks").select("id").eq("spec_id",a),u=l?.length??0;u>0&&await this.supabase.from("tasks").delete().eq("spec_id",a);let{error:d}=await this.supabase.from("specs").delete().eq("id",a);return d?`Failed to delete spec "${e}": ${d.message}`:`Deleted spec "${e}" and ${u} associated task(s).`}async reparentSpec(e,r,n){let s=n||await this.resolveDefaultProjectId(),i=this.supabase.from("specs").select("id, name, parent_spec_id").eq("name",e);s&&(i=i.eq("project_id",s));let{data:o,error:a}=await i.limit(1).single();if(a||!o)return`Spec "${e}" not found.`;let c=o.id;if(r===null){let{error:m}=await this.supabase.from("specs").update({parent_spec_id:null}).eq("id",c);return m?`Failed to reparent spec "${e}": ${m.message}`:`Spec "${e}" is now a top-level spec.`}if(r===e)return`Cannot reparent spec "${e}" to itself.`;let l=this.supabase.from("specs").select("id, name, parent_spec_id").eq("name",r);s&&(l=l.eq("project_id",s));let{data:u,error:d}=await l.limit(1).single();if(d||!u)return`Parent spec "${r}" not found.`;let p=u.id,f=p;for(;f;){if(f===c)return`Cannot reparent: "${r}" is a descendant of "${e}", which would create a circular reference.`;f=(await this.supabase.from("specs").select("parent_spec_id").eq("id",f).limit(1).single()).data?.parent_spec_id??null}let{error:h}=await this.supabase.from("specs").update({parent_spec_id:p}).eq("id",c);return h?`Failed to reparent spec "${e}": ${h.message}`:`Spec "${e}" is now a sub-spec of "${r}".`}async archiveSpec(e,r){let n=r||await this.resolveDefaultProjectId(),s=this.supabase.from("specs").select("id").eq("name",e);n&&(s=s.eq("project_id",n));let{data:i,error:o}=await s.limit(1).single();if(o||!i)return`Spec "${e}" not found.`;let{error:a}=await this.supabase.from("specs").update({status:"archived"}).eq("id",i.id);return a?`Failed to archive spec "${e}": ${a.message}`:`Archived spec "${e}". It will be hidden from default list_specs.`}async deleteTask(e,r,n){let s=await this.resolveSpecId(e,n);if(!s)return`Spec "${e}" not found.`;let{data:i,error:o}=await this.supabase.from("tasks").select("id, task_name").eq("spec_id",s).eq("task_name",r).limit(1).single();if(o||!i)return`Task "${r}" not found for spec "${e}".`;let{data:a}=await this.supabase.from("tasks").select("task_name, dependencies").eq("spec_id",s),c=[];for(let d of a||[]){let p=d.dependencies;p&&p.includes(r)&&c.push(d.task_name)}if(c.length>0)for(let d of c){let p=a.find(f=>f.task_name===d);if(p){let f=(p.dependencies||[]).filter(h=>h!==r);await this.supabase.from("tasks").update({dependencies:f}).eq("spec_id",s).eq("task_name",d)}}let{error:l}=await this.supabase.from("tasks").delete().eq("id",i.id);if(l)return`Failed to delete task "${r}": ${l.message}`;let u=`Deleted task "${r}" from spec "${e}".`;return c.length>0&&(u+=` Updated ${c.length} dependent task(s): ${c.join(", ")}.`),u}async moveTask(e,r,n,s){let i=await this.resolveSpecId(e,s);if(!i)return`Source spec "${e}" not found.`;let o=await this.resolveSpecId(n,s);if(!o)return`Target spec "${n}" not found.`;if(i===o)return"Source and target spec are the same.";let{data:a,error:c}=await this.supabase.from("tasks").select("id").eq("spec_id",i).eq("task_name",r).limit(1).single();if(c||!a)return`Task "${r}" not found for spec "${e}".`;let{data:l}=await this.supabase.from("tasks").select("id").eq("spec_id",o).eq("task_name",r).limit(1).maybeSingle();if(l)return`Task "${r}" already exists in spec "${n}".`;let{error:u}=await this.supabase.from("tasks").update({spec_id:o}).eq("id",a.id);return u?`Failed to move task "${r}": ${u.message}`:`Moved task "${r}" from spec "${e}" to spec "${n}".`}async search(e,r,n){let s=n||await this.resolveDefaultProjectId();if(!s)return"No project found.";let i=[],o=e.toLowerCase();if(!r||r==="specs_only"){let{data:a}=await this.supabase.from("specs").select("name, content, status").eq("project_id",s);for(let c of a||[]){let l=c.content||"",u=c.name;if(u.includes(o)||l.toLowerCase().includes(o)){let p=l.toLowerCase().indexOf(o),f="";if(p>=0){let h=Math.max(0,p-40),m=Math.min(l.length,p+e.length+40);f=l.slice(h,m).replace(/\n/g," ").trim(),h>0&&(f="..."+f),m<l.length&&(f=f+"...")}i.push(`[spec] [${c.status}] ${u}${f?`: ${f}`:""}`)}}}if(!r||r==="tasks_only"){let{data:a}=await this.supabase.from("specs").select("id, name").eq("project_id",s);if(a&&a.length>0){let c=a.map(d=>d.id),l=new Map(a.map(d=>[d.id,d.name])),{data:u}=await this.supabase.from("tasks").select("task_name, objective, context, status, spec_id").in("spec_id",c);for(let d of u||[]){let p=d.task_name,f=d.objective||"",h=d.context||"";if(`${p} ${f} ${h}`.toLowerCase().includes(o)){let g=l.get(d.spec_id)||"unknown";i.push(`[task] [${d.status}] ${g}/${p}: ${f}`)}}}}if(!r||r==="findings_only"){let{data:a}=await this.supabase.from("findings").select("id, content, pile_type, status").eq("project_id",s);for(let c of a||[]){let l=c.content||"";if(l.toLowerCase().includes(o)){let u=l.length>80?l.slice(0,80)+"...":l;i.push(`[${c.pile_type}] [${c.status}] ${u}`)}}}return i.length===0?`No results found for "${e}".`:`Found ${i.length} result(s) for "${e}":
|
|
329
329
|
|
|
330
330
|
${i.join(`
|