@automagik/genie 3.260317.4 → 3.260317.5

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.
@@ -10,7 +10,7 @@
10
10
  "plugins": [
11
11
  {
12
12
  "name": "genie",
13
- "version": "3.260317.2",
13
+ "version": "3.260317.3",
14
14
  "source": "./plugins/genie",
15
15
  "description": "Human-AI partnership for Claude Code. Share a terminal, orchestrate workers, evolve together. Brainstorm ideas, wish them into plans, make with parallel agents, ship as one team. A coding genie that grows with your project."
16
16
  }
package/dist/genie.js CHANGED
@@ -83,7 +83,7 @@ tmux set-option -w pane-active-border-style "fg=$COLOR"
83
83
  `,D.length-B>F&&Q>B)q+=D.slice(B,Q)+`
84
84
  `+D.slice(Q+1);else q+=D.slice(B);return q.slice(1)}function wH(D){var F="",$=0,J;for(var B=0;B<D.length;$>=65536?B+=2:B++)if($=G3(D,B),J=DD[$],!J&&U3($)){if(F+=D[B],$>=65536)F+=D[B+1]}else F+=J||ZH($);return F}function fH(D,F,$){var J="",B=D.tag,X,Q,Y;for(X=0,Q=$.length;X<Q;X+=1){if(Y=$[X],D.replacer)Y=D.replacer.call($,String(X),Y);if(oD(D,F,Y,!1,!1)||typeof Y>"u"&&oD(D,F,null,!1,!1)){if(J!=="")J+=","+(!D.condenseFlow?" ":"");J+=D.dump}}D.tag=B,D.dump="["+J+"]"}function x4(D,F,$,J){var B="",X=D.tag,Q,Y,q;for(Q=0,Y=$.length;Q<Y;Q+=1){if(q=$[Q],D.replacer)q=D.replacer.call($,String(Q),q);if(oD(D,F+1,q,!0,!0,!1,!0)||typeof q>"u"&&oD(D,F+1,null,!0,!0,!1,!0)){if(!J||B!=="")B+=T1(D,F);if(D.dump&&V3===D.dump.charCodeAt(0))B+="-";else B+="- ";B+=D.dump}}D.tag=X,D.dump=B||"[]"}function uH(D,F,$){var J="",B=D.tag,X=Object.keys($),Q,Y,q,G,H;for(Q=0,Y=X.length;Q<Y;Q+=1){if(H="",J!=="")H+=", ";if(D.condenseFlow)H+='"';if(q=X[Q],G=$[q],D.replacer)G=D.replacer.call($,q,G);if(!oD(D,F,q,!1,!1))continue;if(D.dump.length>1024)H+="? ";if(H+=D.dump+(D.condenseFlow?'"':"")+":"+(D.condenseFlow?"":" "),!oD(D,F,G,!1,!1))continue;H+=D.dump,J+=H}D.tag=B,D.dump="{"+J+"}"}function xH(D,F,$,J){var B="",X=D.tag,Q=Object.keys($),Y,q,G,H,V,U;if(D.sortKeys===!0)Q.sort();else if(typeof D.sortKeys==="function")Q.sort(D.sortKeys);else if(D.sortKeys)throw new QD("sortKeys must be a boolean or a function");for(Y=0,q=Q.length;Y<q;Y+=1){if(U="",!J||B!=="")U+=T1(D,F);if(G=Q[Y],H=$[G],D.replacer)H=D.replacer.call($,G,H);if(!oD(D,F+1,G,!0,!0,!0))continue;if(V=D.tag!==null&&D.tag!=="?"||D.dump&&D.dump.length>1024,V)if(D.dump&&V3===D.dump.charCodeAt(0))U+="?";else U+="? ";if(U+=D.dump,V)U+=T1(D,F);if(!oD(D,F+1,H,!0,V))continue;if(D.dump&&V3===D.dump.charCodeAt(0))U+=":";else U+=": ";U+=D.dump,B+=U}D.tag=X,D.dump=B||"{}"}function y4(D,F,$){var J,B,X,Q,Y,q;B=$?D.explicitTypes:D.implicitTypes;for(X=0,Q=B.length;X<Q;X+=1)if(Y=B[X],(Y.instanceOf||Y.predicate)&&(!Y.instanceOf||typeof F==="object"&&F instanceof Y.instanceOf)&&(!Y.predicate||Y.predicate(F))){if($)if(Y.multi&&Y.representName)D.tag=Y.representName(F);else D.tag=Y.tag;else D.tag="?";if(Y.represent){if(q=D.styleMap[Y.tag]||Y.defaultStyle,DF.call(Y.represent)==="[object Function]")J=Y.represent(F,q);else if(FF.call(Y.represent,q))J=Y.represent[q](F,q);else throw new QD("!<"+Y.tag+'> tag resolver accepts not "'+q+'" style');D.dump=J}return!0}return!1}function oD(D,F,$,J,B,X,Q){if(D.tag=null,D.dump=$,!y4(D,$,!1))y4(D,$,!0);var Y=DF.call(D.dump),q=J,G;if(J)J=D.flowLevel<0||D.flowLevel>F;var H=Y==="[object Object]"||Y==="[object Array]",V,U;if(H)V=D.duplicates.indexOf($),U=V!==-1;if(D.tag!==null&&D.tag!=="?"||U||D.indent!==2&&F>0)B=!1;if(U&&D.usedDuplicates[V])D.dump="*ref_"+V;else{if(H&&U&&!D.usedDuplicates[V])D.usedDuplicates[V]=!0;if(Y==="[object Object]"){if(J&&Object.keys(D.dump).length!==0){if(xH(D,F,D.dump,B),U)D.dump="&ref_"+V+D.dump}else if(uH(D,F,D.dump),U)D.dump="&ref_"+V+" "+D.dump}else if(Y==="[object Array]"){if(J&&D.dump.length!==0){if(D.noArrayIndent&&!Q&&F>0)x4(D,F-1,D.dump,B);else x4(D,F,D.dump,B);if(U)D.dump="&ref_"+V+D.dump}else if(fH(D,F,D.dump),U)D.dump="&ref_"+V+" "+D.dump}else if(Y==="[object String]"){if(D.tag!=="?")PH(D,D.dump,F,X,q)}else if(Y==="[object Undefined]")return!1;else{if(D.skipInvalid)return!1;throw new QD("unacceptable kind of an object to dump "+Y)}if(D.tag!==null&&D.tag!=="?"){if(G=encodeURI(D.tag[0]==="!"?D.tag.slice(1):D.tag).replace(/!/g,"%21"),D.tag[0]==="!")G="!"+G;else if(G.slice(0,18)==="tag:yaml.org,2002:")G="!!"+G.slice(18);else G="!<"+G+">";D.dump=G+" "+D.dump}}return!0}function yH(D,F){var $=[],J=[],B,X;S1(D,$,J);for(B=0,X=J.length;B<X;B+=1)F.duplicates.push($[J[B]]);F.usedDuplicates=Array(X)}function S1(D,F,$){var J,B,X;if(D!==null&&typeof D==="object")if(B=F.indexOf(D),B!==-1){if($.indexOf(B)===-1)$.push(B)}else if(F.push(D),Array.isArray(D))for(B=0,X=D.length;B<X;B+=1)S1(D[B],F,$);else{J=Object.keys(D);for(B=0,X=J.length;B<X;B+=1)S1(D[J[B]],F,$)}}function hH(D,F){F=F||{};var $=new NH(F);if(!$.noRefs)yH(D,$);var J=D;if($.replacer)J=$.replacer.call({"":J},"",J);if(oD($,0,J,!0,!0))return $.dump+`
85
85
  `;return""}function k1(D,F){return function(){throw Error("Function yaml."+D+" is removed in js-yaml 4. Use yaml."+F+" instead, which is now safe by default.")}}var Zq,Tq,Nq,Sq,Iq,bq,i,QD,Pq,kq,wq,e,yq,hq,gq,mq,lq,iq,sq,JG,BG,YG,HG,VG,WG,m4,l4,MG,AG,I1=`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=
86
- \r`,_G,LG,ZG,SG,IG,PG,kG,uG,p4,q2,_8=1,d4=2,c4=3,L8=4,_1=1,xG=2,Z4=3,yG,hG,gG,i4,r4,o4,s4,Q2,S4,BH,XH,e4,DF,FF,P1=65279,QH=9,V3=10,YH=13,qH=32,GH=33,HH=34,Z1=35,VH=37,WH=38,UH=39,zH=42,$F=44,KH=45,T8=58,MH=61,EH=62,AH=63,RH=64,JF=91,BF=93,OH=96,XF=123,CH=124,QF=125,DD,jH,_H,TH=1,W3=2,qF=1,N1=2,GF=3,HF=4,Z0=5,gH,mH,VF,DR,FR,$R,JR,BR;var WF=S(()=>{/*! js-yaml 4.1.1 https://github.com/nodeca/js-yaml @license MIT */Zq=h4,Tq=Oq,Nq=Cq,Sq=_q,Iq=Lq,bq=jq,i={isNothing:Zq,isObject:Tq,toArray:Nq,repeat:Sq,isNegativeZero:Iq,extend:bq};H3.prototype=Object.create(Error.prototype);H3.prototype.constructor=H3;H3.prototype.toString=function(F){return this.name+": "+g4(this,F)};QD=H3;Pq=vq,kq=["kind","multi","resolve","construct","instanceOf","predicate","represent","representName","defaultStyle","styleAliases"],wq=["scalar","sequence","mapping"];e=uq;L1.prototype.extend=function(F){var $=[],J=[];if(F instanceof e)J.push(F);else if(Array.isArray(F))J=J.concat(F);else if(F&&(Array.isArray(F.implicit)||Array.isArray(F.explicit))){if(F.implicit)$=$.concat(F.implicit);if(F.explicit)J=J.concat(F.explicit)}else throw new QD("Schema.extend argument should be a Type, [ Type ], or a schema definition ({ implicit: [...], explicit: [...] })");$.forEach(function(X){if(!(X instanceof e))throw new QD("Specified list of YAML types (or a single Type object) contains a non-Type object.");if(X.loadKind&&X.loadKind!=="scalar")throw new QD("There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.");if(X.multi)throw new QD("There is a multi type in the implicit list of a schema. Multi tags can only be listed as explicit.")}),J.forEach(function(X){if(!(X instanceof e))throw new QD("Specified list of YAML types (or a single Type object) contains a non-Type object.")});var B=Object.create(L1.prototype);return B.implicit=(this.implicit||[]).concat($),B.explicit=(this.explicit||[]).concat(J),B.compiledImplicit=L4(B,"implicit"),B.compiledExplicit=L4(B,"explicit"),B.compiledTypeMap=xq(B.compiledImplicit,B.compiledExplicit),B};yq=L1,hq=new e("tag:yaml.org,2002:str",{kind:"scalar",construct:function(D){return D!==null?D:""}}),gq=new e("tag:yaml.org,2002:seq",{kind:"sequence",construct:function(D){return D!==null?D:[]}}),mq=new e("tag:yaml.org,2002:map",{kind:"mapping",construct:function(D){return D!==null?D:{}}}),lq=new yq({explicit:[hq,gq,mq]});iq=new e("tag:yaml.org,2002:null",{kind:"scalar",resolve:pq,construct:dq,predicate:cq,represent:{canonical:function(){return"~"},lowercase:function(){return"null"},uppercase:function(){return"NULL"},camelcase:function(){return"Null"},empty:function(){return""}},defaultStyle:"lowercase"});sq=new e("tag:yaml.org,2002:bool",{kind:"scalar",resolve:rq,construct:nq,predicate:oq,represent:{lowercase:function(D){return D?"true":"false"},uppercase:function(D){return D?"TRUE":"FALSE"},camelcase:function(D){return D?"True":"False"}},defaultStyle:"lowercase"});JG=new e("tag:yaml.org,2002:int",{kind:"scalar",resolve:DG,construct:FG,predicate:$G,represent:{binary:function(D){return D>=0?"0b"+D.toString(2):"-0b"+D.toString(2).slice(1)},octal:function(D){return D>=0?"0o"+D.toString(8):"-0o"+D.toString(8).slice(1)},decimal:function(D){return D.toString(10)},hexadecimal:function(D){return D>=0?"0x"+D.toString(16).toUpperCase():"-0x"+D.toString(16).toUpperCase().slice(1)}},defaultStyle:"decimal",styleAliases:{binary:[2,"bin"],octal:[8,"oct"],decimal:[10,"dec"],hexadecimal:[16,"hex"]}}),BG=new RegExp("^(?:[-+]?(?:[0-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$");YG=/^[-+]?[0-9]+e/;HG=new e("tag:yaml.org,2002:float",{kind:"scalar",resolve:XG,construct:QG,predicate:GG,represent:qG,defaultStyle:"lowercase"}),VG=lq.extend({implicit:[iq,sq,JG,HG]}),WG=VG,m4=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"),l4=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$");MG=new e("tag:yaml.org,2002:timestamp",{kind:"scalar",resolve:UG,construct:zG,instanceOf:Date,represent:KG});AG=new e("tag:yaml.org,2002:merge",{kind:"scalar",resolve:EG});_G=new e("tag:yaml.org,2002:binary",{kind:"scalar",resolve:RG,construct:OG,predicate:jG,represent:CG}),LG=Object.prototype.hasOwnProperty,ZG=Object.prototype.toString;SG=new e("tag:yaml.org,2002:omap",{kind:"sequence",resolve:TG,construct:NG}),IG=Object.prototype.toString;PG=new e("tag:yaml.org,2002:pairs",{kind:"sequence",resolve:bG,construct:vG}),kG=Object.prototype.hasOwnProperty;uG=new e("tag:yaml.org,2002:set",{kind:"mapping",resolve:wG,construct:fG}),p4=WG.extend({implicit:[MG,AG],explicit:[_G,SG,PG,uG]}),q2=Object.prototype.hasOwnProperty,yG=/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/,hG=/[\x85\u2028\u2029]/,gG=/[,\[\]\{\}]/,i4=/^(?:!|!!|![a-z\-]+!)$/i,r4=/^(?:!|[^,\[\]\{\}])(?:%[0-9a-f]{2}|[0-9a-z\-#;\/\?:@&=\+\$,_\.!~\*'\(\)\[\]])*$/i;o4=Array(256),s4=Array(256);for(Q2=0;Q2<256;Q2++)o4[Q2]=N4(Q2)?1:0,s4[Q2]=N4(Q2);S4={YAML:function(F,$,J){var B,X,Q;if(F.version!==null)L(F,"duplication of %YAML directive");if(J.length!==1)L(F,"YAML directive accepts exactly one argument");if(B=/^([0-9]+)\.([0-9]+)$/.exec(J[0]),B===null)L(F,"ill-formed argument of the YAML directive");if(X=parseInt(B[1],10),Q=parseInt(B[2],10),X!==1)L(F,"unacceptable YAML version of the document");if(F.version=J[0],F.checkLineBreaks=Q<2,Q!==1&&Q!==2)Z8(F,"unsupported YAML version of the document")},TAG:function(F,$,J){var B,X;if(J.length!==2)L(F,"TAG directive accepts exactly two arguments");if(B=J[0],X=J[1],!i4.test(B))L(F,"ill-formed tag handle (first argument) of the TAG directive");if(q2.call(F.tagMap,B))L(F,'there is a previously declared suffix for "'+B+'" tag handle');if(!r4.test(X))L(F,"ill-formed tag prefix (second argument) of the TAG directive");try{X=decodeURIComponent(X)}catch(Q){L(F,"tag prefix is malformed: "+X)}F.tagMap[B]=X}};BH=$H,XH=JH,e4={loadAll:BH,load:XH},DF=Object.prototype.toString,FF=Object.prototype.hasOwnProperty,DD={};DD[0]="\\0";DD[7]="\\a";DD[8]="\\b";DD[9]="\\t";DD[10]="\\n";DD[11]="\\v";DD[12]="\\f";DD[13]="\\r";DD[27]="\\e";DD[34]="\\\"";DD[92]="\\\\";DD[133]="\\N";DD[160]="\\_";DD[8232]="\\L";DD[8233]="\\P";jH=["y","Y","yes","Yes","YES","on","On","ON","n","N","no","No","NO","off","Off","OFF"],_H=/^[-+]?[0-9_]+(?::[0-9_]+)+(?:\.[0-9_]*)?$/;gH=hH,mH={dump:gH};VF=e4.load,DR=e4.loadAll,FR=mH.dump,$R=k1("safeLoad","load"),JR=k1("safeLoadAll","loadAll"),BR=k1("safeDump","dump")});import{existsSync as w1,readFileSync as pH,readdirSync as dH,realpathSync as cH}from"fs";import{dirname as I8,join as f1,resolve as b8}from"path";function iH(){let D=cH(process.argv[1]||""),F=[b8(I8(D),".."),b8(I8(D),"..",".."),b8(I8(import.meta.dir??__dirname),"..",".."),b8(I8(import.meta.dir??__dirname),"..")];for(let $ of F)if(w1(f1($,"plugins","genie","agents")))return $;return F[0]}function rH(D){let F=D.match(/^---\n([\s\S]*?)\n---/);if(!F)return{};try{return VF(F[1])??{}}catch{return{}}}function nH(D){if(!w1(D))return[];let F=[],$;try{$=dH(D,{withFileTypes:!0})}catch{return[]}for(let J of $){if(!J.isDirectory())continue;let B=f1(D,J.name,"AGENTS.md");if(!w1(B))continue;let X=pH(B,"utf-8"),Q=rH(X),Y=Q.name||J.name,q=Y.startsWith("council");F.push({name:Y,description:Q.description||"",agentPath:B,model:Q.model==="inherit"?void 0:Q.model,promptMode:Q.promptMode||void 0,category:q?"council":"role",color:Q.color})}return F}function sH(D){return v8.find((F)=>F.name===D)??null}function zF(D){return sH(D)?.agentPath??null}var __dirname="/home/runner/_work/genie/genie/src/lib",oH,u1,UF,z3,v8;var K3=S(()=>{WF();oH=f1(iH(),"plugins","genie","agents"),u1=nH(oH),UF=u1.filter((D)=>D.category==="role"),z3=u1.filter((D)=>D.category==="council"),v8=u1});var R3={};JD(R3,{rm:()=>p1,resolve:()=>E3,ls:()=>A3,loadIdentity:()=>c1,getProjectRoot:()=>EF,get:()=>$V,edit:()=>d1,add:()=>l1});import{execSync as x1}from"child_process";import{existsSync as M3}from"fs";import{mkdir as MF,readFile as aH,writeFile as tH}from"fs/promises";import{homedir as eH}from"os";import{dirname as y1,join as H2}from"path";function DV(){return process.env.GENIE_HOME??H2(eH(),".genie")}function h1(){return H2(DV(),"agent-directory.json")}function EF(){if(process.env.GENIE_PROJECT_ROOT)return process.env.GENIE_PROJECT_ROOT;try{return x1("git rev-parse --show-toplevel",{encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()}catch{return process.cwd()}}function AF(){try{let D=x1("git rev-parse --git-common-dir",{encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim(),F=x1("git rev-parse --show-toplevel",{encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim(),{resolve:$}=P("path"),J=$(D),B=y1(J);if(B===F)return null;return B}catch{return null}}function g1(){return H2(EF(),".genie","agents.json")}function P8(D){return D?h1():g1()}async function G2(D){try{let F=await aH(D,"utf-8");return JSON.parse(F)}catch{return{entries:{},lastUpdated:new Date().toISOString()}}}async function FV(D,F){await MF(y1(F),{recursive:!0}),D.lastUpdated=new Date().toISOString(),await tH(F,JSON.stringify(D,null,2))}async function m1(D,F){await MF(y1(D),{recursive:!0});let $=await HD(D);try{let J=await G2(D),B=await F(J);return await FV(J,D),B}finally{await $()}}async function l1(D,F){if(!D.name||D.name.trim()==="")throw Error("Agent name is required.");if(!D.dir||D.dir.trim()==="")throw Error("Agent directory (--dir) is required.");if(!M3(D.dir))throw Error(`Directory does not exist: ${D.dir}`);let $=H2(D.dir,"AGENTS.md");if(!M3($))throw Error(`AGENTS.md not found in ${D.dir}. Each agent directory must contain an AGENTS.md file.`);let J={...D,promptMode:D.promptMode??"append",registeredAt:new Date().toISOString()},B=P8(F?.global);return await m1(B,(X)=>{if(X.entries[D.name])throw Error(`Agent "${D.name}" already exists. Use "genie dir edit" to update or "genie dir rm" first.`);X.entries[D.name]=J}),J}async function p1(D,F){let $=!1,J=P8(F?.global);return await m1(J,(B)=>{if(B.entries[D])delete B.entries[D],$=!0}),$}async function E3(D){let $=(await G2(g1())).entries[D];if($)return{entry:$,builtin:!1};let J=AF();if(J){let q=H2(J,".genie","agents.json"),H=(await G2(q)).entries[D];if(H)return{entry:H,builtin:!1}}let X=(await G2(h1())).entries[D];if(X)return{entry:X,builtin:!1};let Q=UF.find((q)=>q.name===D);if(Q)return{entry:KF(Q),builtin:!0};let Y=z3.find((q)=>q.name===D);if(Y)return{entry:KF(Y),builtin:!0};return null}async function A3(){let D=[],F=new Set,$=await G2(g1());for(let X of Object.values($.entries))D.push({...X,scope:"project"}),F.add(X.name);let J=AF();if(J){let X=H2(J,".genie","agents.json"),Q=await G2(X);for(let Y of Object.values(Q.entries))if(!F.has(Y.name))D.push({...Y,scope:"project"}),F.add(Y.name)}let B=await G2(h1());for(let X of Object.values(B.entries))if(!F.has(X.name))D.push({...X,scope:"global"}),F.add(X.name);return D}async function $V(D,F){let $=P8(F?.global);return(await G2($)).entries[D]??null}async function d1(D,F,$){let J=null,B=P8($?.global);if(await m1(B,(X)=>{let Q=X.entries[D];if(!Q)throw Error(`Agent "${D}" not found in directory.`);if(F.dir){if(!M3(F.dir))throw Error(`Directory does not exist: ${F.dir}`);let Y=H2(F.dir,"AGENTS.md");if(!M3(Y))throw Error(`AGENTS.md not found in ${F.dir}.`)}Object.assign(Q,F),J=Q}),!J)throw Error(`Agent "${D}" not found in directory.`);return J}function c1(D){let F=H2(D.dir,"AGENTS.md");if(M3(F))return F;return null}function KF(D){return{name:D.name,dir:"",promptMode:D.promptMode??"append",model:D.model,roles:[],registeredAt:"(built-in)"}}var O3=S(()=>{K3();w2()});function CF(D){return XV.has(D)}var C3,XV;var i1=S(()=>{C3=["PreToolUse","PostToolUse","SessionStart","SessionEnd","TeammateIdle","TaskCompleted"],XV=new Set(["PreToolUse","UserPromptSubmit","TeammateIdle","TaskCompleted","PermissionRequest"])});function k8(D,F="mosaic"){return`select-layout -t '${D}' ${F==="vertical"?"even-horizontal":"tiled"}`}function w8(D){if(D==="vertical")return"vertical";return"mosaic"}var _3={};JD(_3,{validateBranchName:()=>SF,setTeamStatus:()=>l8,pruneStaleWorktrees:()=>IF,listTeams:()=>g8,listMembers:()=>a1,killTeamMembers:()=>m8,hireAgent:()=>h8,getTeam:()=>AD,fireAgent:()=>o1,disbandTeam:()=>s1,createTeam:()=>n1});import{existsSync as f8}from"fs";import{mkdir as LF,readFile as u8,readdir as ZF,rm as zV,unlink as TF,writeFile as x8}from"fs/promises";import{homedir as KV}from"os";import j3,{join as aD}from"path";var{$:sD}=globalThis.Bun;function NF(){return process.env.GENIE_HOME??aD(KV(),".genie")}function y8(){return aD(NF(),"teams")}function MV(D){return D.replace(/\//g,"--")}function I0(D){let F=MV(j3.basename(D)===D?D:D);return aD(y8(),`${F}.json`)}function EV(D){let $=q0().terminal?.worktreeBase;if($){if(j3.isAbsolute($))return $;return aD(D,$)}let J=j3.basename(D);return aD(NF(),"worktrees",J)}function SF(D){let F=[];if(/\s/.test(D))F.push("contains spaces");if(D.includes(".."))F.push('contains ".."');if(D.includes("~"))F.push('contains "~"');if(D.includes("^"))F.push('contains "^"');if(D.includes(":"))F.push('contains ":"');if(D.includes("?"))F.push('contains "?"');if(D.includes("*"))F.push('contains "*"');if(D.includes("["))F.push('contains "["');if(D.includes("\\"))F.push('contains "\\"');if(/[\x00-\x1f\x7f]/.test(D))F.push("contains control characters");if(D.endsWith(".lock"))F.push('ends with ".lock"');if(D.endsWith("/"))F.push('ends with "/"');if(D.endsWith("."))F.push('ends with "."');if(D.startsWith("-"))F.push('starts with "-"');if(F.length>0)throw Error(`Invalid team name '${D}': must be a valid git branch name (${F.join(", ")})`)}async function r1(D){let $=(await p()).filter((J)=>J.role===D||J.id===D);for(let J of $){try{if(J.paneId&&J.paneId!=="inline"){let{execSync:B}=P("child_process");B(`tmux kill-pane -t ${J.paneId}`,{stdio:"ignore"})}}catch{}await wD(J.id)}}async function AV(D,F,$,J){try{await sD`git -C ${D} fetch origin ${J}`.quiet()}catch{}if(await LF(j3.dirname($),{recursive:!0}),f8($))return;let B=!1;try{await sD`git -C ${D} rev-parse --verify ${F}`.quiet(),B=!0}catch{}if(B){await sD`git -C ${D} worktree add ${$} ${F}`.quiet();return}try{await sD`git -C ${D} worktree add -b ${F} ${$} origin/${J}`.quiet()}catch{try{await sD`git -C ${D} worktree add -b ${F} ${$} ${J}`.quiet()}catch{await sD`git -C ${D} worktree add -b ${F} ${$}`.quiet()}}}async function n1(D,F,$="dev"){SF(D);let J=j3.resolve(F),B=y8();await LF(B,{recursive:!0});let X=I0(D);if(f8(X)){let H=await u8(X,"utf-8");return JSON.parse(H)}let Q=EV(J),Y=aD(Q,D);await AV(J,D,Y,$);let q=new Date().toISOString(),G={name:D,repo:J,baseBranch:$,worktreePath:Y,members:[],status:"in_progress",createdAt:q};if(z4()){G.nativeTeamsEnabled=!0;try{let H=await K4(D);G.nativeTeamParentSessionId=H.sessionId}catch{}}return await x8(X,JSON.stringify(G,null,2)),G}async function h8(D,F){let $=await AD(D);if(!$)throw Error(`Team "${D}" not found.`);let J;if(F==="council")J=z3.map((Q)=>Q.name).filter((Q)=>!$.members.includes(Q)),$.members.push(...J);else{if($.members.includes(F))return[];$.members.push(F),J=[F]}let B=I0(D);return await x8(B,JSON.stringify($,null,2)),J}async function o1(D,F){let $=await AD(D);if(!$)throw Error(`Team "${D}" not found.`);let J=$.members.indexOf(F);if(J===-1)return!1;$.members.splice(J,1);let B=I0(D);await x8(B,JSON.stringify($,null,2));try{await r1(F)}catch{}return!0}async function s1(D){let F=await AD(D);if(!F)return!1;if(F.nativeTeamsEnabled)try{await Q3(D)}catch{}for(let B of F.members)try{await r1(B)}catch{}let $=F.repo;if(F.worktreePath&&f8(F.worktreePath))try{await sD`git -C ${$} worktree remove ${F.worktreePath} --force`.quiet()}catch{try{await zV(F.worktreePath,{recursive:!0,force:!0}),await sD`git -C ${$} worktree prune`.quiet()}catch{}}let J=I0(D);try{await TF(J)}catch{return!1}return await IF($),!0}async function IF(D){let F=y8(),$;try{$=await ZF(F)}catch{return}for(let J of $){if(!J.endsWith(".json"))continue;try{let B=await u8(aD(F,J),"utf-8"),X=JSON.parse(B);if(X.worktreePath&&!f8(X.worktreePath))await TF(aD(F,J))}catch{}}try{await sD`git -C ${D} worktree prune`.quiet()}catch{}}async function AD(D){try{let F=await u8(I0(D),"utf-8");return JSON.parse(F)}catch{return null}}async function g8(){let D=y8();try{let F=await ZF(D),$=[];for(let J of F){if(!J.endsWith(".json"))continue;try{let B=await u8(aD(D,J),"utf-8");$.push(JSON.parse(B))}catch{}}return $}catch{return[]}}async function a1(D){let F=await AD(D);if(!F)return null;return F.members}async function m8(D){let F=await AD(D);if(!F)return;for(let $ of F.members)try{await r1($)}catch{}}async function l8(D,F){let $=I0(D),J=await HD($);try{let B=await AD(D);if(!B)throw Error(`Team "${D}" not found.`);B.status=F,await x8($,JSON.stringify(B,null,2))}finally{await J()}}var L3=S(()=>{KD();K3();m2();w2();lD()});var kF={};JD(kF,{isTeamHooked:()=>NV,injectTeamHooks:()=>TV});import{existsSync as bF}from"fs";import{mkdir as RV,readFile as vF,writeFile as OV}from"fs/promises";import{homedir as CV}from"os";import{join as t1}from"path";function _V(){return process.env.CLAUDE_CONFIG_DIR??t1(CV(),".claude")}function PF(D){let F=D.replace(/[^a-zA-Z0-9]/g,"-").toLowerCase();return t1(_V(),"teams",F,"settings.json")}function LV(){let D={};for(let F of C3)D[F]=[{hooks:[{type:"command",command:p8,timeout:jV}]}];return D}async function ZV(D){let F={};if(bF(D))try{let Q=await vF(D,"utf-8");F=JSON.parse(Q)}catch{}let $=LV(),J=F.hooks;if(J){if(C3.every((Y)=>{return J[Y]?.some((G)=>G.hooks?.some((H)=>H.command===p8))}))return!1}let B=J?{...J}:{};for(let Q of C3){let Y=$[Q][0],q=B[Q]??[];if(!q.some((H)=>H.hooks?.some((V)=>V.command===p8)))B[Q]=[...q,Y]}F.hooks=B;let X=t1(D,"..");return await RV(X,{recursive:!0}),await OV(D,JSON.stringify(F,null,2)),!0}async function TV(D){let F=PF(D);return ZV(F)}async function NV(D){let F=PF(D);if(!bF(F))return!1;try{let $=await vF(F,"utf-8"),B=JSON.parse($).hooks;if(!B)return!1;return C3.every((X)=>{return B[X]?.some((Y)=>Y.hooks?.some((q)=>q.command===p8))})}catch{return!1}}var p8="genie hook dispatch",jV=15;var wF=S(()=>{i1()});var hF={};JD(hF,{suspendWorker:()=>yF,getIdleTimeoutMs:()=>xF,checkIdleWorkers:()=>IV,WATCHDOG_POLL_INTERVAL_MS:()=>SV});function xF(){let D=process.env.GENIE_IDLE_TIMEOUT_MS;if(D!==void 0){if(D==="")return fF;let F=Number(D);if(!Number.isNaN(F)&&F>=0)return F}return fF}async function yF(D,F=uF){let $=await F.registryGet(D);if(!$)return!1;if($.state==="suspended")return!0;if($.paneId&&$.paneId!=="inline")try{await F.executeTmux(`kill-pane -t '${$.paneId}'`)}catch{}return await F.registryUpdate(D,{state:"suspended",suspendedAt:new Date().toISOString()}),!0}async function IV(D=uF){let F=xF();if(F===0)return[];let $=await D.registryList(),J=[];for(let B of $){if(B.state!=="idle")continue;if(Date.now()-new Date(B.lastStateChange).getTime()<F)continue;if(!await D.isPaneAlive(B.paneId)){await D.registryUpdate(B.id,{state:"suspended",suspendedAt:new Date().toISOString()}),J.push(B.id);continue}if(await yF(B.id,D))J.push(B.id)}return J}var uF,fF=1800000,SV=60000;var gF=S(()=>{KD();FD();uF={registryGet:iD,registryList:p,registryUpdate:q1,executeTmux:f,isPaneAlive:TD}});var iF={};JD(iF,{handleWorkerStop:()=>D5,handleWorkerSpawn:()=>V2,handleWorkerKill:()=>e1,handleLsCommand:()=>F5});function mF(D){let{readFileSync:F,existsSync:$}=P("fs");if(!$(D))return!1;try{let J=Number.parseInt(F(D,"utf-8").trim());if(J>0)return process.kill(J,0),!0}catch{}return!1}async function bV(D){let{writeFileSync:F,mkdirSync:$}=P("fs"),{join:J}=P("path"),{homedir:B}=P("os"),X=J(B(),".genie","relay");$(X,{recursive:!0});let Q=J(X,"otel-relay.pid"),Y=J(X,"otel-relay.mjs");if(mF(Q))return!0;let q=J(process.env.CLAUDE_CONFIG_DIR??J(B(),".claude"),"teams",D,"inboxes"),G=X.replace(/\\/g,"\\\\").replace(/'/g,"\\'"),H=q.replace(/\\/g,"\\\\").replace(/'/g,"\\'"),V=Q.replace(/\\/g,"\\\\").replace(/'/g,"\\'");try{F(Y,`import { createServer } from 'http';
86
+ \r`,_G,LG,ZG,SG,IG,PG,kG,uG,p4,q2,_8=1,d4=2,c4=3,L8=4,_1=1,xG=2,Z4=3,yG,hG,gG,i4,r4,o4,s4,Q2,S4,BH,XH,e4,DF,FF,P1=65279,QH=9,V3=10,YH=13,qH=32,GH=33,HH=34,Z1=35,VH=37,WH=38,UH=39,zH=42,$F=44,KH=45,T8=58,MH=61,EH=62,AH=63,RH=64,JF=91,BF=93,OH=96,XF=123,CH=124,QF=125,DD,jH,_H,TH=1,W3=2,qF=1,N1=2,GF=3,HF=4,Z0=5,gH,mH,VF,DR,FR,$R,JR,BR;var WF=S(()=>{/*! js-yaml 4.1.1 https://github.com/nodeca/js-yaml @license MIT */Zq=h4,Tq=Oq,Nq=Cq,Sq=_q,Iq=Lq,bq=jq,i={isNothing:Zq,isObject:Tq,toArray:Nq,repeat:Sq,isNegativeZero:Iq,extend:bq};H3.prototype=Object.create(Error.prototype);H3.prototype.constructor=H3;H3.prototype.toString=function(F){return this.name+": "+g4(this,F)};QD=H3;Pq=vq,kq=["kind","multi","resolve","construct","instanceOf","predicate","represent","representName","defaultStyle","styleAliases"],wq=["scalar","sequence","mapping"];e=uq;L1.prototype.extend=function(F){var $=[],J=[];if(F instanceof e)J.push(F);else if(Array.isArray(F))J=J.concat(F);else if(F&&(Array.isArray(F.implicit)||Array.isArray(F.explicit))){if(F.implicit)$=$.concat(F.implicit);if(F.explicit)J=J.concat(F.explicit)}else throw new QD("Schema.extend argument should be a Type, [ Type ], or a schema definition ({ implicit: [...], explicit: [...] })");$.forEach(function(X){if(!(X instanceof e))throw new QD("Specified list of YAML types (or a single Type object) contains a non-Type object.");if(X.loadKind&&X.loadKind!=="scalar")throw new QD("There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.");if(X.multi)throw new QD("There is a multi type in the implicit list of a schema. Multi tags can only be listed as explicit.")}),J.forEach(function(X){if(!(X instanceof e))throw new QD("Specified list of YAML types (or a single Type object) contains a non-Type object.")});var B=Object.create(L1.prototype);return B.implicit=(this.implicit||[]).concat($),B.explicit=(this.explicit||[]).concat(J),B.compiledImplicit=L4(B,"implicit"),B.compiledExplicit=L4(B,"explicit"),B.compiledTypeMap=xq(B.compiledImplicit,B.compiledExplicit),B};yq=L1,hq=new e("tag:yaml.org,2002:str",{kind:"scalar",construct:function(D){return D!==null?D:""}}),gq=new e("tag:yaml.org,2002:seq",{kind:"sequence",construct:function(D){return D!==null?D:[]}}),mq=new e("tag:yaml.org,2002:map",{kind:"mapping",construct:function(D){return D!==null?D:{}}}),lq=new yq({explicit:[hq,gq,mq]});iq=new e("tag:yaml.org,2002:null",{kind:"scalar",resolve:pq,construct:dq,predicate:cq,represent:{canonical:function(){return"~"},lowercase:function(){return"null"},uppercase:function(){return"NULL"},camelcase:function(){return"Null"},empty:function(){return""}},defaultStyle:"lowercase"});sq=new e("tag:yaml.org,2002:bool",{kind:"scalar",resolve:rq,construct:nq,predicate:oq,represent:{lowercase:function(D){return D?"true":"false"},uppercase:function(D){return D?"TRUE":"FALSE"},camelcase:function(D){return D?"True":"False"}},defaultStyle:"lowercase"});JG=new e("tag:yaml.org,2002:int",{kind:"scalar",resolve:DG,construct:FG,predicate:$G,represent:{binary:function(D){return D>=0?"0b"+D.toString(2):"-0b"+D.toString(2).slice(1)},octal:function(D){return D>=0?"0o"+D.toString(8):"-0o"+D.toString(8).slice(1)},decimal:function(D){return D.toString(10)},hexadecimal:function(D){return D>=0?"0x"+D.toString(16).toUpperCase():"-0x"+D.toString(16).toUpperCase().slice(1)}},defaultStyle:"decimal",styleAliases:{binary:[2,"bin"],octal:[8,"oct"],decimal:[10,"dec"],hexadecimal:[16,"hex"]}}),BG=new RegExp("^(?:[-+]?(?:[0-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$");YG=/^[-+]?[0-9]+e/;HG=new e("tag:yaml.org,2002:float",{kind:"scalar",resolve:XG,construct:QG,predicate:GG,represent:qG,defaultStyle:"lowercase"}),VG=lq.extend({implicit:[iq,sq,JG,HG]}),WG=VG,m4=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"),l4=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$");MG=new e("tag:yaml.org,2002:timestamp",{kind:"scalar",resolve:UG,construct:zG,instanceOf:Date,represent:KG});AG=new e("tag:yaml.org,2002:merge",{kind:"scalar",resolve:EG});_G=new e("tag:yaml.org,2002:binary",{kind:"scalar",resolve:RG,construct:OG,predicate:jG,represent:CG}),LG=Object.prototype.hasOwnProperty,ZG=Object.prototype.toString;SG=new e("tag:yaml.org,2002:omap",{kind:"sequence",resolve:TG,construct:NG}),IG=Object.prototype.toString;PG=new e("tag:yaml.org,2002:pairs",{kind:"sequence",resolve:bG,construct:vG}),kG=Object.prototype.hasOwnProperty;uG=new e("tag:yaml.org,2002:set",{kind:"mapping",resolve:wG,construct:fG}),p4=WG.extend({implicit:[MG,AG],explicit:[_G,SG,PG,uG]}),q2=Object.prototype.hasOwnProperty,yG=/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/,hG=/[\x85\u2028\u2029]/,gG=/[,\[\]\{\}]/,i4=/^(?:!|!!|![a-z\-]+!)$/i,r4=/^(?:!|[^,\[\]\{\}])(?:%[0-9a-f]{2}|[0-9a-z\-#;\/\?:@&=\+\$,_\.!~\*'\(\)\[\]])*$/i;o4=Array(256),s4=Array(256);for(Q2=0;Q2<256;Q2++)o4[Q2]=N4(Q2)?1:0,s4[Q2]=N4(Q2);S4={YAML:function(F,$,J){var B,X,Q;if(F.version!==null)L(F,"duplication of %YAML directive");if(J.length!==1)L(F,"YAML directive accepts exactly one argument");if(B=/^([0-9]+)\.([0-9]+)$/.exec(J[0]),B===null)L(F,"ill-formed argument of the YAML directive");if(X=parseInt(B[1],10),Q=parseInt(B[2],10),X!==1)L(F,"unacceptable YAML version of the document");if(F.version=J[0],F.checkLineBreaks=Q<2,Q!==1&&Q!==2)Z8(F,"unsupported YAML version of the document")},TAG:function(F,$,J){var B,X;if(J.length!==2)L(F,"TAG directive accepts exactly two arguments");if(B=J[0],X=J[1],!i4.test(B))L(F,"ill-formed tag handle (first argument) of the TAG directive");if(q2.call(F.tagMap,B))L(F,'there is a previously declared suffix for "'+B+'" tag handle');if(!r4.test(X))L(F,"ill-formed tag prefix (second argument) of the TAG directive");try{X=decodeURIComponent(X)}catch(Q){L(F,"tag prefix is malformed: "+X)}F.tagMap[B]=X}};BH=$H,XH=JH,e4={loadAll:BH,load:XH},DF=Object.prototype.toString,FF=Object.prototype.hasOwnProperty,DD={};DD[0]="\\0";DD[7]="\\a";DD[8]="\\b";DD[9]="\\t";DD[10]="\\n";DD[11]="\\v";DD[12]="\\f";DD[13]="\\r";DD[27]="\\e";DD[34]="\\\"";DD[92]="\\\\";DD[133]="\\N";DD[160]="\\_";DD[8232]="\\L";DD[8233]="\\P";jH=["y","Y","yes","Yes","YES","on","On","ON","n","N","no","No","NO","off","Off","OFF"],_H=/^[-+]?[0-9_]+(?::[0-9_]+)+(?:\.[0-9_]*)?$/;gH=hH,mH={dump:gH};VF=e4.load,DR=e4.loadAll,FR=mH.dump,$R=k1("safeLoad","load"),JR=k1("safeLoadAll","loadAll"),BR=k1("safeDump","dump")});import{existsSync as w1,readFileSync as pH,readdirSync as dH,realpathSync as cH}from"fs";import{dirname as I8,join as f1,resolve as b8}from"path";function iH(){let D=cH(process.argv[1]||""),F=[b8(I8(D),".."),b8(I8(D),"..",".."),b8(I8(import.meta.dir??__dirname),"..",".."),b8(I8(import.meta.dir??__dirname),"..")];for(let $ of F)if(w1(f1($,"plugins","genie","agents")))return $;return F[0]}function rH(D){let F=D.match(/^---\n([\s\S]*?)\n---/);if(!F)return{};try{return VF(F[1])??{}}catch{return{}}}function nH(D){if(!w1(D))return[];let F=[],$;try{$=dH(D,{withFileTypes:!0})}catch{return[]}for(let J of $){if(!J.isDirectory())continue;let B=f1(D,J.name,"AGENTS.md");if(!w1(B))continue;let X=pH(B,"utf-8"),Q=rH(X),Y=Q.name||J.name,q=Y.startsWith("council");F.push({name:Y,description:Q.description||"",agentPath:B,model:Q.model==="inherit"?void 0:Q.model,promptMode:Q.promptMode||void 0,category:q?"council":"role",color:Q.color})}return F}function sH(D){return v8.find((F)=>F.name===D)??null}function zF(D){return sH(D)?.agentPath??null}var __dirname="/home/runner/_work/genie/genie/src/lib",oH,u1,UF,z3,v8;var K3=S(()=>{WF();oH=f1(iH(),"plugins","genie","agents"),u1=nH(oH),UF=u1.filter((D)=>D.category==="role"),z3=u1.filter((D)=>D.category==="council"),v8=u1});var R3={};JD(R3,{rm:()=>p1,resolve:()=>E3,ls:()=>A3,loadIdentity:()=>c1,getProjectRoot:()=>EF,get:()=>$V,edit:()=>d1,add:()=>l1});import{execSync as x1}from"child_process";import{existsSync as M3}from"fs";import{mkdir as MF,readFile as aH,writeFile as tH}from"fs/promises";import{homedir as eH}from"os";import{dirname as y1,join as H2}from"path";function DV(){return process.env.GENIE_HOME??H2(eH(),".genie")}function h1(){return H2(DV(),"agent-directory.json")}function EF(){if(process.env.GENIE_PROJECT_ROOT)return process.env.GENIE_PROJECT_ROOT;try{return x1("git rev-parse --show-toplevel",{encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()}catch{return process.cwd()}}function AF(){try{let D=x1("git rev-parse --git-common-dir",{encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim(),F=x1("git rev-parse --show-toplevel",{encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim(),{resolve:$}=P("path"),J=$(D),B=y1(J);if(B===F)return null;return B}catch{return null}}function g1(){return H2(EF(),".genie","agents.json")}function P8(D){return D?h1():g1()}async function G2(D){try{let F=await aH(D,"utf-8");return JSON.parse(F)}catch{return{entries:{},lastUpdated:new Date().toISOString()}}}async function FV(D,F){await MF(y1(F),{recursive:!0}),D.lastUpdated=new Date().toISOString(),await tH(F,JSON.stringify(D,null,2))}async function m1(D,F){await MF(y1(D),{recursive:!0});let $=await HD(D);try{let J=await G2(D),B=await F(J);return await FV(J,D),B}finally{await $()}}async function l1(D,F){if(!D.name||D.name.trim()==="")throw Error("Agent name is required.");if(!D.dir||D.dir.trim()==="")throw Error("Agent directory (--dir) is required.");if(!M3(D.dir))throw Error(`Directory does not exist: ${D.dir}`);let $=H2(D.dir,"AGENTS.md");if(!M3($))throw Error(`AGENTS.md not found in ${D.dir}. Each agent directory must contain an AGENTS.md file.`);let J={...D,promptMode:D.promptMode??"append",registeredAt:new Date().toISOString()},B=P8(F?.global);return await m1(B,(X)=>{if(X.entries[D.name])throw Error(`Agent "${D.name}" already exists. Use "genie dir edit" to update or "genie dir rm" first.`);X.entries[D.name]=J}),J}async function p1(D,F){let $=!1,J=P8(F?.global);return await m1(J,(B)=>{if(B.entries[D])delete B.entries[D],$=!0}),$}async function E3(D){let $=(await G2(g1())).entries[D];if($)return{entry:$,builtin:!1};let J=AF();if(J){let q=H2(J,".genie","agents.json"),H=(await G2(q)).entries[D];if(H)return{entry:H,builtin:!1}}let X=(await G2(h1())).entries[D];if(X)return{entry:X,builtin:!1};let Q=UF.find((q)=>q.name===D);if(Q)return{entry:KF(Q),builtin:!0};let Y=z3.find((q)=>q.name===D);if(Y)return{entry:KF(Y),builtin:!0};return null}async function A3(){let D=[],F=new Set,$=await G2(g1());for(let X of Object.values($.entries))D.push({...X,scope:"project"}),F.add(X.name);let J=AF();if(J){let X=H2(J,".genie","agents.json"),Q=await G2(X);for(let Y of Object.values(Q.entries))if(!F.has(Y.name))D.push({...Y,scope:"project"}),F.add(Y.name)}let B=await G2(h1());for(let X of Object.values(B.entries))if(!F.has(X.name))D.push({...X,scope:"global"}),F.add(X.name);return D}async function $V(D,F){let $=P8(F?.global);return(await G2($)).entries[D]??null}async function d1(D,F,$){let J=null,B=P8($?.global);if(await m1(B,(X)=>{let Q=X.entries[D];if(!Q)throw Error(`Agent "${D}" not found in directory.`);if(F.dir){if(!M3(F.dir))throw Error(`Directory does not exist: ${F.dir}`);let Y=H2(F.dir,"AGENTS.md");if(!M3(Y))throw Error(`AGENTS.md not found in ${F.dir}.`)}Object.assign(Q,F),J=Q}),!J)throw Error(`Agent "${D}" not found in directory.`);return J}function c1(D){let F=H2(D.dir,"AGENTS.md");if(M3(F))return F;return null}function KF(D){return{name:D.name,dir:"",promptMode:D.promptMode??"append",model:D.model,roles:[],registeredAt:"(built-in)"}}var O3=S(()=>{K3();w2()});function CF(D){return XV.has(D)}var C3,XV;var i1=S(()=>{C3=["PreToolUse","PostToolUse","SessionStart","SessionEnd","TeammateIdle","TaskCompleted"],XV=new Set(["PreToolUse","UserPromptSubmit","TeammateIdle","TaskCompleted","PermissionRequest"])});function k8(D,F="mosaic"){return`select-layout -t '${D}' ${F==="vertical"?"even-horizontal":"tiled"}`}function w8(D){if(D==="vertical")return"vertical";return"mosaic"}var _3={};JD(_3,{validateBranchName:()=>SF,setTeamStatus:()=>l8,pruneStaleWorktrees:()=>IF,listTeams:()=>g8,listMembers:()=>a1,killTeamMembers:()=>m8,hireAgent:()=>h8,getTeam:()=>AD,fireAgent:()=>o1,disbandTeam:()=>s1,createTeam:()=>n1});import{existsSync as f8}from"fs";import{mkdir as LF,readFile as u8,readdir as ZF,rm as zV,unlink as TF,writeFile as x8}from"fs/promises";import{homedir as KV}from"os";import j3,{join as aD}from"path";var{$:sD}=globalThis.Bun;function NF(){return process.env.GENIE_HOME??aD(KV(),".genie")}function y8(){return aD(NF(),"teams")}function MV(D){return D.replace(/\//g,"--")}function I0(D){let F=MV(j3.basename(D)===D?D:D);return aD(y8(),`${F}.json`)}function EV(D){let $=q0().terminal?.worktreeBase;if($){if(j3.isAbsolute($))return $;return aD(D,$)}let J=j3.basename(D);return aD(NF(),"worktrees",J)}function SF(D){let F=[];if(/\s/.test(D))F.push("contains spaces");if(D.includes(".."))F.push('contains ".."');if(D.includes("~"))F.push('contains "~"');if(D.includes("^"))F.push('contains "^"');if(D.includes(":"))F.push('contains ":"');if(D.includes("?"))F.push('contains "?"');if(D.includes("*"))F.push('contains "*"');if(D.includes("["))F.push('contains "["');if(D.includes("\\"))F.push('contains "\\"');if(/[\x00-\x1f\x7f]/.test(D))F.push("contains control characters");if(D.endsWith(".lock"))F.push('ends with ".lock"');if(D.endsWith("/"))F.push('ends with "/"');if(D.endsWith("."))F.push('ends with "."');if(D.startsWith("-"))F.push('starts with "-"');if(F.length>0)throw Error(`Invalid team name '${D}': must be a valid git branch name (${F.join(", ")})`)}async function r1(D,F){let J=(await p()).filter((B)=>(B.role===D||B.id===D)&&(!F||B.team===F));for(let B of J){try{if(B.paneId&&B.paneId!=="inline"){let{execSync:X}=P("child_process");X(`tmux kill-pane -t ${B.paneId}`,{stdio:"ignore"})}}catch{}await wD(B.id)}}async function AV(D,F,$,J){try{await sD`git -C ${D} fetch origin ${J}`.quiet()}catch{}if(await LF(j3.dirname($),{recursive:!0}),f8($))return;let B=!1;try{await sD`git -C ${D} rev-parse --verify ${F}`.quiet(),B=!0}catch{}if(B){await sD`git -C ${D} worktree add ${$} ${F}`.quiet();return}try{await sD`git -C ${D} worktree add -b ${F} ${$} origin/${J}`.quiet()}catch{try{await sD`git -C ${D} worktree add -b ${F} ${$} ${J}`.quiet()}catch{await sD`git -C ${D} worktree add -b ${F} ${$}`.quiet()}}}async function n1(D,F,$="dev"){SF(D);let J=j3.resolve(F),B=y8();await LF(B,{recursive:!0});let X=I0(D);if(f8(X)){let H=await u8(X,"utf-8");return JSON.parse(H)}let Q=EV(J),Y=aD(Q,D);await AV(J,D,Y,$);let q=new Date().toISOString(),G={name:D,repo:J,baseBranch:$,worktreePath:Y,members:[],status:"in_progress",createdAt:q};if(z4()){G.nativeTeamsEnabled=!0;try{let H=await K4(D);G.nativeTeamParentSessionId=H.sessionId}catch{}}return await x8(X,JSON.stringify(G,null,2)),G}async function h8(D,F){let $=await AD(D);if(!$)throw Error(`Team "${D}" not found.`);let J;if(F==="council")J=z3.map((Q)=>Q.name).filter((Q)=>!$.members.includes(Q)),$.members.push(...J);else{if($.members.includes(F))return[];$.members.push(F),J=[F]}let B=I0(D);return await x8(B,JSON.stringify($,null,2)),J}async function o1(D,F){let $=await AD(D);if(!$)throw Error(`Team "${D}" not found.`);let J=$.members.indexOf(F);if(J===-1)return!1;$.members.splice(J,1);let B=I0(D);await x8(B,JSON.stringify($,null,2));try{await r1(F)}catch{}return!0}async function s1(D){let F=await AD(D);if(!F)return!1;if(F.nativeTeamsEnabled)try{await Q3(D)}catch{}for(let B of F.members)try{await r1(B,D)}catch{}let $=F.repo;if(F.worktreePath&&f8(F.worktreePath))try{await sD`git -C ${$} worktree remove ${F.worktreePath} --force`.quiet()}catch{try{await zV(F.worktreePath,{recursive:!0,force:!0}),await sD`git -C ${$} worktree prune`.quiet()}catch{}}let J=I0(D);try{await TF(J)}catch{return!1}return await IF($),!0}async function IF(D){let F=y8(),$;try{$=await ZF(F)}catch{return}for(let J of $){if(!J.endsWith(".json"))continue;try{let B=await u8(aD(F,J),"utf-8"),X=JSON.parse(B);if(X.worktreePath&&!f8(X.worktreePath))await TF(aD(F,J))}catch{}}try{await sD`git -C ${D} worktree prune`.quiet()}catch{}}async function AD(D){try{let F=await u8(I0(D),"utf-8");return JSON.parse(F)}catch{return null}}async function g8(){let D=y8();try{let F=await ZF(D),$=[];for(let J of F){if(!J.endsWith(".json"))continue;try{let B=await u8(aD(D,J),"utf-8");$.push(JSON.parse(B))}catch{}}return $}catch{return[]}}async function a1(D){let F=await AD(D);if(!F)return null;return F.members}async function m8(D){let F=await AD(D);if(!F)return;for(let $ of F.members)try{await r1($,D)}catch{}}async function l8(D,F){let $=I0(D),J=await HD($);try{let B=await AD(D);if(!B)throw Error(`Team "${D}" not found.`);B.status=F,await x8($,JSON.stringify(B,null,2))}finally{await J()}}var L3=S(()=>{KD();K3();m2();w2();lD()});var kF={};JD(kF,{isTeamHooked:()=>NV,injectTeamHooks:()=>TV});import{existsSync as bF}from"fs";import{mkdir as RV,readFile as vF,writeFile as OV}from"fs/promises";import{homedir as CV}from"os";import{join as t1}from"path";function _V(){return process.env.CLAUDE_CONFIG_DIR??t1(CV(),".claude")}function PF(D){let F=D.replace(/[^a-zA-Z0-9]/g,"-").toLowerCase();return t1(_V(),"teams",F,"settings.json")}function LV(){let D={};for(let F of C3)D[F]=[{hooks:[{type:"command",command:p8,timeout:jV}]}];return D}async function ZV(D){let F={};if(bF(D))try{let Q=await vF(D,"utf-8");F=JSON.parse(Q)}catch{}let $=LV(),J=F.hooks;if(J){if(C3.every((Y)=>{return J[Y]?.some((G)=>G.hooks?.some((H)=>H.command===p8))}))return!1}let B=J?{...J}:{};for(let Q of C3){let Y=$[Q][0],q=B[Q]??[];if(!q.some((H)=>H.hooks?.some((V)=>V.command===p8)))B[Q]=[...q,Y]}F.hooks=B;let X=t1(D,"..");return await RV(X,{recursive:!0}),await OV(D,JSON.stringify(F,null,2)),!0}async function TV(D){let F=PF(D);return ZV(F)}async function NV(D){let F=PF(D);if(!bF(F))return!1;try{let $=await vF(F,"utf-8"),B=JSON.parse($).hooks;if(!B)return!1;return C3.every((X)=>{return B[X]?.some((Y)=>Y.hooks?.some((q)=>q.command===p8))})}catch{return!1}}var p8="genie hook dispatch",jV=15;var wF=S(()=>{i1()});var hF={};JD(hF,{suspendWorker:()=>yF,getIdleTimeoutMs:()=>xF,checkIdleWorkers:()=>IV,WATCHDOG_POLL_INTERVAL_MS:()=>SV});function xF(){let D=process.env.GENIE_IDLE_TIMEOUT_MS;if(D!==void 0){if(D==="")return fF;let F=Number(D);if(!Number.isNaN(F)&&F>=0)return F}return fF}async function yF(D,F=uF){let $=await F.registryGet(D);if(!$)return!1;if($.state==="suspended")return!0;if($.paneId&&$.paneId!=="inline")try{await F.executeTmux(`kill-pane -t '${$.paneId}'`)}catch{}return await F.registryUpdate(D,{state:"suspended",suspendedAt:new Date().toISOString()}),!0}async function IV(D=uF){let F=xF();if(F===0)return[];let $=await D.registryList(),J=[];for(let B of $){if(B.state!=="idle")continue;if(Date.now()-new Date(B.lastStateChange).getTime()<F)continue;if(!await D.isPaneAlive(B.paneId)){await D.registryUpdate(B.id,{state:"suspended",suspendedAt:new Date().toISOString()}),J.push(B.id);continue}if(await yF(B.id,D))J.push(B.id)}return J}var uF,fF=1800000,SV=60000;var gF=S(()=>{KD();FD();uF={registryGet:iD,registryList:p,registryUpdate:q1,executeTmux:f,isPaneAlive:TD}});var iF={};JD(iF,{handleWorkerStop:()=>D5,handleWorkerSpawn:()=>V2,handleWorkerKill:()=>e1,handleLsCommand:()=>F5});function mF(D){let{readFileSync:F,existsSync:$}=P("fs");if(!$(D))return!1;try{let J=Number.parseInt(F(D,"utf-8").trim());if(J>0)return process.kill(J,0),!0}catch{}return!1}async function bV(D){let{writeFileSync:F,mkdirSync:$}=P("fs"),{join:J}=P("path"),{homedir:B}=P("os"),X=J(B(),".genie","relay");$(X,{recursive:!0});let Q=J(X,"otel-relay.pid"),Y=J(X,"otel-relay.mjs");if(mF(Q))return!0;let q=J(process.env.CLAUDE_CONFIG_DIR??J(B(),".claude"),"teams",D,"inboxes"),G=X.replace(/\\/g,"\\\\").replace(/'/g,"\\'"),H=q.replace(/\\/g,"\\\\").replace(/'/g,"\\'"),V=Q.replace(/\\/g,"\\\\").replace(/'/g,"\\'");try{F(Y,`import { createServer } from 'http';
87
87
  import { execSync } from 'child_process';
88
88
  import { readFileSync, writeFileSync, mkdirSync, readdirSync, unlinkSync, statSync } from 'fs';
89
89
  import { createHash } from 'crypto';
@@ -446,7 +446,7 @@ Wish: ${F.wish}`),console.log("\u2500".repeat(60));let $=Object.entries(F.groups
446
446
  `)}function MW(){try{let D=Q$("git diff HEAD",{encoding:"utf-8",maxBuffer:1048576}),F=Q$("git diff --cached",{encoding:"utf-8",maxBuffer:1048576}),$=[D,F].filter(Boolean).join(`
447
447
  `);if($.length>50000)return`${$.slice(0,50000)}
448
448
 
449
- ... (diff truncated at 50KB)`;return $}catch{return""}}function EW(D){let F=[],$=/^### Group (\d+):/gim,J=$.exec(D);while(J!==null){let B=J[1],X=J.index,Q=D.slice(X+J[0].length),Y=Q.search(/^### Group \d+:/m),G=(Y!==-1?Q.slice(0,Y):Q).match(/\*\*depends-on:\*\*\s*(.+)/i),H=[];if(G){let V=G[1].trim();if(V.toLowerCase()!=="none")H=V.split(",").map((U)=>U.trim().replace(/^group\s*/i,"")).filter(Boolean)}F.push({name:B,dependsOn:H}),J=$.exec(D)}return F}async function AW(D,F){let $=b0(process.cwd(),".genie","brainstorms",F,"DRAFT.md");if(!i8($))console.error(`\u274C Draft not found: ${$}`),console.error(` Create it first: mkdir -p .genie/brainstorms/${F} && touch .genie/brainstorms/${F}/DRAFT.md`),process.exit(1);let J=await r8($,"utf-8"),B=o8({filePath:$,sectionContent:J,command:"brainstorm",skill:"brainstorm"}),X=await n8(B);console.log(`\uD83D\uDCDD Dispatching brainstorm to ${D} for "${F}"`),console.log(` Draft: ${$}`),await V2(D,{provider:"claude",team:process.env.GENIE_TEAM??"genie",extraArgs:["--append-system-prompt-file",X],initialPrompt:`Brainstorm "${F}". Your context is in the system prompt. Explore the idea, ask clarifying questions, and build toward a design.`})}async function RW(D,F){let $=b0(process.cwd(),".genie","brainstorms",F,"DESIGN.md");if(!i8($))console.error(`\u274C Design not found: ${$}`),console.error(` Run brainstorm first: genie brainstorm <agent> ${F}`),process.exit(1);let J=await r8($,"utf-8"),B=o8({filePath:$,sectionContent:J,command:"wish",skill:"wish"}),X=await n8(B);console.log(`\uD83D\uDCDD Dispatching wish to ${D} for "${F}"`),console.log(` Design: ${$}`),await V2(D,{provider:"claude",team:process.env.GENIE_TEAM??"genie",extraArgs:["--append-system-prompt-file",X],initialPrompt:`Create a wish from the design for "${F}". Your context is in the system prompt. Write the WISH.md with execution groups, acceptance criteria, and validation commands.`})}async function OW(D,F){let{slug:$,group:J}=S3(F),B=b0(process.cwd(),".genie","wishes",$,"WISH.md");if(!i8(B))console.error(`\u274C Wish not found: ${B}`),console.error(` Create it first: genie wish <agent> ${$}`),process.exit(1);let X=await r8(B,"utf-8"),Q=Y$(X,J);if(!Q){console.error(`\u274C Group "${J}" not found in ${B}`),console.error(" Available groups:");let V=X.match(/^### Group \d+:.*$/gm);if(V)for(let U of V)console.error(` ${U}`);process.exit(1)}let Y=await T3($);if(!Y){let V=EW(X);Y=await D$($,V),console.log(`\uD83D\uDCDD Initialized state for wish "${$}" (${V.length} groups)`)}try{await F$($,J,D),console.log(`\u2705 Group "${J}" set to in_progress (assigned to ${D})`)}catch(V){let U=V instanceof Error?V.message:String(V);console.error(`\u274C ${U}`),process.exit(1)}let q=q$(X),G=o8({filePath:B,sectionContent:Q,wishContext:q,command:`work ${F}`,skill:"work"}),H=await n8(G);console.log(`\uD83D\uDD27 Dispatching work to ${D} for "${F}"`),console.log(` Wish: ${B}`),console.log(` Group: ${J}`),await V2(D,{provider:"claude",team:process.env.GENIE_TEAM??"genie",extraArgs:["--append-system-prompt-file",H],initialPrompt:`Execute Group ${J} of wish "${$}". Your full context is in the system prompt. Read the wish at ${B} if needed. Implement all deliverables, run validation, and report completion.`})}async function CW(D,F){let{slug:$,group:J}=S3(F),B=b0(process.cwd(),".genie","wishes",$,"WISH.md");if(!i8(B))console.error(`\u274C Wish not found: ${B}`),process.exit(1);let X=await r8(B,"utf-8"),Q=Y$(X,J);if(!Q)console.error(`\u274C Group "${J}" not found in ${B}`),process.exit(1);let Y=MW(),q=q$(X),G=[Q,"","## Git Diff (changes to review)","",Y?`\`\`\`diff
449
+ ... (diff truncated at 50KB)`;return $}catch{return""}}function EW(D){let F=[],$=/^### Group ([A-Za-z0-9]+):/gim,J=$.exec(D);while(J!==null){let B=J[1],X=J.index,Q=D.slice(X+J[0].length),Y=Q.search(/^### Group [A-Za-z0-9]+:/m),G=(Y!==-1?Q.slice(0,Y):Q).match(/\*\*depends-on:\*\*\s*(.+)/i),H=[];if(G){let V=G[1].trim();if(V.toLowerCase()!=="none")H=V.split(",").map((U)=>U.trim().replace(/^group\s*/i,"")).filter(Boolean)}F.push({name:B,dependsOn:H}),J=$.exec(D)}return F}async function AW(D,F){let $=b0(process.cwd(),".genie","brainstorms",F,"DRAFT.md");if(!i8($))console.error(`\u274C Draft not found: ${$}`),console.error(` Create it first: mkdir -p .genie/brainstorms/${F} && touch .genie/brainstorms/${F}/DRAFT.md`),process.exit(1);let J=await r8($,"utf-8"),B=o8({filePath:$,sectionContent:J,command:"brainstorm",skill:"brainstorm"}),X=await n8(B);console.log(`\uD83D\uDCDD Dispatching brainstorm to ${D} for "${F}"`),console.log(` Draft: ${$}`),await V2(D,{provider:"claude",team:process.env.GENIE_TEAM??"genie",extraArgs:["--append-system-prompt-file",X],initialPrompt:`Brainstorm "${F}". Your context is in the system prompt. Explore the idea, ask clarifying questions, and build toward a design.`})}async function RW(D,F){let $=b0(process.cwd(),".genie","brainstorms",F,"DESIGN.md");if(!i8($))console.error(`\u274C Design not found: ${$}`),console.error(` Run brainstorm first: genie brainstorm <agent> ${F}`),process.exit(1);let J=await r8($,"utf-8"),B=o8({filePath:$,sectionContent:J,command:"wish",skill:"wish"}),X=await n8(B);console.log(`\uD83D\uDCDD Dispatching wish to ${D} for "${F}"`),console.log(` Design: ${$}`),await V2(D,{provider:"claude",team:process.env.GENIE_TEAM??"genie",extraArgs:["--append-system-prompt-file",X],initialPrompt:`Create a wish from the design for "${F}". Your context is in the system prompt. Write the WISH.md with execution groups, acceptance criteria, and validation commands.`})}async function OW(D,F){let{slug:$,group:J}=S3(F),B=b0(process.cwd(),".genie","wishes",$,"WISH.md");if(!i8(B))console.error(`\u274C Wish not found: ${B}`),console.error(` Create it first: genie wish <agent> ${$}`),process.exit(1);let X=await r8(B,"utf-8"),Q=Y$(X,J);if(!Q){console.error(`\u274C Group "${J}" not found in ${B}`),console.error(" Available groups:");let V=X.match(/^### Group [A-Za-z0-9]+:.*$/gm);if(V)for(let U of V)console.error(` ${U}`);process.exit(1)}let Y=await T3($);if(!Y){let V=EW(X);Y=await D$($,V),console.log(`\uD83D\uDCDD Initialized state for wish "${$}" (${V.length} groups)`)}try{await F$($,J,D),console.log(`\u2705 Group "${J}" set to in_progress (assigned to ${D})`)}catch(V){let U=V instanceof Error?V.message:String(V);console.error(`\u274C ${U}`),process.exit(1)}let q=q$(X),G=o8({filePath:B,sectionContent:Q,wishContext:q,command:`work ${F}`,skill:"work"}),H=await n8(G);console.log(`\uD83D\uDD27 Dispatching work to ${D} for "${F}"`),console.log(` Wish: ${B}`),console.log(` Group: ${J}`),await V2(D,{provider:"claude",team:process.env.GENIE_TEAM??"genie",extraArgs:["--append-system-prompt-file",H],initialPrompt:`Execute Group ${J} of wish "${$}". Your full context is in the system prompt. Read the wish at ${B} if needed. Implement all deliverables, run validation, and report completion.`})}async function CW(D,F){let{slug:$,group:J}=S3(F),B=b0(process.cwd(),".genie","wishes",$,"WISH.md");if(!i8(B))console.error(`\u274C Wish not found: ${B}`),process.exit(1);let X=await r8(B,"utf-8"),Q=Y$(X,J);if(!Q)console.error(`\u274C Group "${J}" not found in ${B}`),process.exit(1);let Y=MW(),q=q$(X),G=[Q,"","## Git Diff (changes to review)","",Y?`\`\`\`diff
450
450
  ${Y}
451
451
  \`\`\``:"(no uncommitted changes found \u2014 review committed changes)"].join(`
452
452
  `),H=o8({filePath:B,sectionContent:G,wishContext:q,command:`review ${F}`,skill:"review"}),V=await n8(H);if(console.log(`\uD83D\uDD0D Dispatching review to ${D} for "${F}"`),console.log(` Wish: ${B}`),console.log(` Group: ${J}`),Y)console.log(` Diff: ${Y.split(`
@@ -0,0 +1,9 @@
1
+
2
+
3
+ ### 🐛 Bug Fixes
4
+ - **core:** scope killWorkersByName by team — prevents killing other teams' workers ([`8dab7e7`](https://github.com/automagik-dev/genie/commit/8dab7e7d4f1bd3a65064508bb82db2917eab57f0))
5
+ - **dispatch:** accept lettered group names (A, B) not just numbered (1, 2) ([`f142f0c`](https://github.com/automagik-dev/genie/commit/f142f0c956284c1fae76a40dfcaa62d5c986a86f))
6
+ - **core:** team-lead prompt — skip status check before first dispatch ([`b6c6870`](https://github.com/automagik-dev/genie/commit/b6c687017a787b50e8587f66a935c9c85ec3f4ea))
7
+
8
+ ### 👥 Contributors
9
+ - Test User
@@ -2,7 +2,7 @@
2
2
  "id": "genie",
3
3
  "name": "Genie",
4
4
  "description": "Skills, agents, and hooks for the Genie CLI terminal orchestration toolkit",
5
- "version": "3.260317.2",
5
+ "version": "3.260317.3",
6
6
  "configSchema": {
7
7
  "type": "object",
8
8
  "additionalProperties": false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automagik/genie",
3
- "version": "3.260317.4",
3
+ "version": "3.260317.5",
4
4
  "description": "Collaborative terminal toolkit for human + AI workflows",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genie",
3
- "version": "3.260317.2",
3
+ "version": "3.260317.3",
4
4
  "description": "Human-AI partnership for Claude Code. Share a terminal, orchestrate workers, evolve together. Brainstorm ideas, turn them into wishes, execute with /work, validate with /review, and ship as one team.",
5
5
  "author": {
6
6
  "name": "Namastex Labs"
@@ -44,18 +44,18 @@ For cross-session agents, use `genie send '<text>' --to <agent>` via Bash.
44
44
  <lifecycle>
45
45
 
46
46
  ## Phase 1 — Read Wish
47
- Read the WISH.md at the path provided in your initial prompt. Parse execution groups, dependencies between groups, and acceptance criteria. Understand the full scope before dispatching anything.
47
+ Read the WISH.md at the path provided in your initial prompt. Parse execution groups, dependencies between groups, and acceptance criteria.
48
48
 
49
- **Gate:** All groups parsed, dependency DAG verified (no circular deps), acceptance criteria extracted. If wish is unparseable or missing groups, report to PM and stop.
49
+ **Gate:** All groups parsed, dependency DAG understood. If wish is unparseable or missing groups, report to PM and stop.
50
50
 
51
51
  ## Phase 2 — Execute Groups
52
- Dispatch groups whose dependencies are satisfied. Run independent groups in parallel. Never start a group before its dependencies complete.
52
+ Dispatch groups whose dependencies are satisfied. `genie work` auto-initializes state on first call do NOT run `genie status` before your first dispatch. Just dispatch immediately.
53
53
 
54
54
  ```bash
55
- genie work engineer <slug>#<group> # Dispatches and spawns engineer
55
+ genie work engineer <slug>#<group> # Auto-inits state, sets in_progress, spawns engineer
56
56
  genie read <team>-engineer # Monitor progress
57
57
  genie done <slug>#<group> # Mark group complete
58
- genie status <slug> # Check overall progress
58
+ genie status <slug> # Check progress (only AFTER first dispatch)
59
59
  ```
60
60
 
61
61
  One group per engineer dispatch. Wait for completion before marking done.
@@ -44,18 +44,18 @@ For cross-session agents, use `genie send '<text>' --to <agent>` via Bash.
44
44
  <lifecycle>
45
45
 
46
46
  ## Phase 1 — Read Wish
47
- Read the WISH.md at the path provided in your initial prompt. Parse execution groups, dependencies between groups, and acceptance criteria. Understand the full scope before dispatching anything.
47
+ Read the WISH.md at the path provided in your initial prompt. Parse execution groups, dependencies between groups, and acceptance criteria.
48
48
 
49
- **Gate:** All groups parsed, dependency DAG verified (no circular deps), acceptance criteria extracted. If wish is unparseable or missing groups, report to PM and stop.
49
+ **Gate:** All groups parsed, dependency DAG understood. If wish is unparseable or missing groups, report to PM and stop.
50
50
 
51
51
  ## Phase 2 — Execute Groups
52
- Dispatch groups whose dependencies are satisfied. Run independent groups in parallel. Never start a group before its dependencies complete.
52
+ Dispatch groups whose dependencies are satisfied. `genie work` auto-initializes state on first call do NOT run `genie status` before your first dispatch. Just dispatch immediately.
53
53
 
54
54
  ```bash
55
- genie work engineer <slug>#<group> # Dispatches and spawns engineer
55
+ genie work engineer <slug>#<group> # Auto-inits state, sets in_progress, spawns engineer
56
56
  genie read <team>-engineer # Monitor progress
57
57
  genie done <slug>#<group> # Mark group complete
58
- genie status <slug> # Check overall progress
58
+ genie status <slug> # Check progress (only AFTER first dispatch)
59
59
  ```
60
60
 
61
61
  One group per engineer dispatch. Wait for completion before marking done.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genie-plugin",
3
- "version": "3.260317.2",
3
+ "version": "3.260317.3",
4
4
  "private": true,
5
5
  "description": "Runtime dependencies for genie bundled CLIs",
6
6
  "type": "module",
@@ -120,10 +120,12 @@ export function validateBranchName(name: string): void {
120
120
  // Agent Kill Helper
121
121
  // ============================================================================
122
122
 
123
- /** Best-effort kill all running workers matching a given agent name (by role or id). */
124
- async function killWorkersByName(agentName: string): Promise<void> {
123
+ /** Best-effort kill all running workers matching a given agent name, scoped to a team. */
124
+ async function killWorkersByName(agentName: string, teamName?: string): Promise<void> {
125
125
  const workers = await registry.list();
126
- const matches = workers.filter((w) => w.role === agentName || w.id === agentName);
126
+ const matches = workers.filter(
127
+ (w) => (w.role === agentName || w.id === agentName) && (!teamName || w.team === teamName),
128
+ );
127
129
  for (const w of matches) {
128
130
  try {
129
131
  if (w.paneId && w.paneId !== 'inline') {
@@ -312,10 +314,10 @@ export async function disbandTeam(teamName: string): Promise<boolean> {
312
314
  }
313
315
  }
314
316
 
315
- // Kill all running team members
317
+ // Kill all running team members (scoped to this team only)
316
318
  for (const member of config.members) {
317
319
  try {
318
- await killWorkersByName(member);
320
+ await killWorkersByName(member, teamName);
319
321
  } catch {
320
322
  // Best-effort — continue with other members
321
323
  }
@@ -426,14 +428,14 @@ export async function listMembers(teamName: string): Promise<string[] | null> {
426
428
  return config.members;
427
429
  }
428
430
 
429
- /** Kill all running workers for a team's members. Best-effortcontinues on failure. */
431
+ /** Kill all running workers for a team's members. Scoped to the team won't kill other teams' workers. */
430
432
  export async function killTeamMembers(teamName: string): Promise<void> {
431
433
  const config = await getTeam(teamName);
432
434
  if (!config) return;
433
435
 
434
436
  for (const member of config.members) {
435
437
  try {
436
- await killWorkersByName(member);
438
+ await killWorkersByName(member, teamName);
437
439
  } catch {
438
440
  // Best-effort — continue with other members
439
441
  }
@@ -140,11 +140,12 @@ function getGitDiff(): string {
140
140
 
141
141
  /**
142
142
  * Parse WISH.md content to extract group definitions for state initialization.
143
- * Looks for `### Group <N>: <title>` headings and `**depends-on:**` lines.
143
+ * Looks for `### Group <id>: <title>` headings and `**depends-on:**` lines.
144
+ * Accepts both numbered (Group 1) and lettered (Group A) identifiers.
144
145
  */
145
146
  export function parseWishGroups(content: string): GroupDefinition[] {
146
147
  const groups: GroupDefinition[] = [];
147
- const groupPattern = /^### Group (\d+):/gim;
148
+ const groupPattern = /^### Group ([A-Za-z0-9]+):/gim;
148
149
 
149
150
  let match: RegExpExecArray | null = groupPattern.exec(content);
150
151
  while (match !== null) {
@@ -153,7 +154,7 @@ export function parseWishGroups(content: string): GroupDefinition[] {
153
154
 
154
155
  // Find the next group heading or end of content
155
156
  const rest = content.slice(start + match[0].length);
156
- const nextGroupIdx = rest.search(/^### Group \d+:/m);
157
+ const nextGroupIdx = rest.search(/^### Group [A-Za-z0-9]+:/m);
157
158
  const section = nextGroupIdx !== -1 ? rest.slice(0, nextGroupIdx) : rest;
158
159
 
159
160
  // Look for **depends-on:** line within this group section
@@ -274,7 +275,7 @@ export async function workDispatchCommand(agentName: string, ref: string): Promi
274
275
  if (!groupSection) {
275
276
  console.error(`❌ Group "${group}" not found in ${wishPath}`);
276
277
  console.error(' Available groups:');
277
- const groups = content.match(/^### Group \d+:.*$/gm);
278
+ const groups = content.match(/^### Group [A-Za-z0-9]+:.*$/gm);
278
279
  if (groups) {
279
280
  for (const g of groups) console.error(` ${g}`);
280
281
  }