@automagik/genie 4.260420.9 → 4.260420.10

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/genie.js CHANGED
@@ -495,22 +495,29 @@ ${bin} set-option -w pane-active-border-style "fg=$COLOR"
495
495
  SELECT e.state FROM executors e
496
496
  JOIN agents a ON a.current_executor_id = e.id
497
497
  WHERE a.id = ${agentId}
498
- `;return rows.length>0?rows[0].state:"offline"}async function listAgents(filters){let sql=await getConnection(),rows;if(filters?.team&&filters?.role)rows=await sql`
498
+ `;return rows.length>0?rows[0].state:"offline"}async function listAgents(filters){let sql=await getConnection(),includeArchived=filters?.includeArchived??!1,rows;if(filters?.team&&filters?.role)rows=await sql`
499
499
  SELECT id, started_at, role, custom_name, team, native_agent_id, native_color,
500
500
  native_team_enabled, parent_session_id, current_executor_id, reports_to, title, created_at, updated_at
501
- FROM agents WHERE team = ${filters.team} AND role = ${filters.role}
501
+ FROM agents
502
+ WHERE team = ${filters.team} AND role = ${filters.role}
503
+ AND (${includeArchived} OR state IS DISTINCT FROM 'archived')
502
504
  `;else if(filters?.team)rows=await sql`
503
505
  SELECT id, started_at, role, custom_name, team, native_agent_id, native_color,
504
506
  native_team_enabled, parent_session_id, current_executor_id, reports_to, title, created_at, updated_at
505
- FROM agents WHERE team = ${filters.team}
507
+ FROM agents
508
+ WHERE team = ${filters.team}
509
+ AND (${includeArchived} OR state IS DISTINCT FROM 'archived')
506
510
  `;else if(filters?.role)rows=await sql`
507
511
  SELECT id, started_at, role, custom_name, team, native_agent_id, native_color,
508
512
  native_team_enabled, parent_session_id, current_executor_id, reports_to, title, created_at, updated_at
509
- FROM agents WHERE role = ${filters.role}
513
+ FROM agents
514
+ WHERE role = ${filters.role}
515
+ AND (${includeArchived} OR state IS DISTINCT FROM 'archived')
510
516
  `;else rows=await sql`
511
517
  SELECT id, started_at, role, custom_name, team, native_agent_id, native_color,
512
518
  native_team_enabled, parent_session_id, current_executor_id, reports_to, title, created_at, updated_at
513
519
  FROM agents
520
+ WHERE (${includeArchived} OR state IS DISTINCT FROM 'archived')
514
521
  `;return rows.map(rowToAgentIdentity)}var init_agent_registry=__esm(()=>{init_audit();init_db();init_tmux()});function normalizeValue(v){if(v===void 0||v===null)return;if(v==="")return;if(v==="inherit")return;return v}function resolveField(agent,field,ctx){return resolveFieldWithSource(agent,field,ctx).value}function resolveFieldWithSource(agent,field,ctx){let agentVal=normalizeValue(agent[field]);if(agentVal!==void 0)return{value:agentVal,source:"explicit"};if(ctx.parent){let parentVal=normalizeValue(ctx.parent.fields[field]);if(parentVal!==void 0)return{value:parentVal,source:`parent:${ctx.parent.name}`}}if(ctx.workspaceDefaults){let wsVal=normalizeValue(ctx.workspaceDefaults[field]);if(wsVal!==void 0)return{value:wsVal,source:"workspace"}}return{value:BUILTIN_DEFAULTS[field],source:"built-in"}}function computeEffectiveDefaults(workspaceDefaults){if(!workspaceDefaults)return{...BUILTIN_DEFAULTS};let result2={...BUILTIN_DEFAULTS};for(let key of Object.keys(BUILTIN_DEFAULTS)){let wsVal=normalizeValue(workspaceDefaults[key]);if(wsVal!==void 0)result2[key]=wsVal}return result2}var BUILTIN_DEFAULTS,RESOLVED_FIELDS;var init_defaults=__esm(()=>{BUILTIN_DEFAULTS={model:"opus",promptMode:"append",color:"blue",effort:"high",thinking:"enabled",permissionMode:"bypassPermissions"},RESOLVED_FIELDS=["model"]});var exports_js_yaml={};__export(exports_js_yaml,{types:()=>types3,safeLoadAll:()=>safeLoadAll,safeLoad:()=>safeLoad,safeDump:()=>safeDump,loadAll:()=>loadAll,load:()=>load2,dump:()=>dump,default:()=>jsYaml,YAMLException:()=>YAMLException,Type:()=>Type,Schema:()=>Schema,JSON_SCHEMA:()=>JSON_SCHEMA,FAILSAFE_SCHEMA:()=>FAILSAFE_SCHEMA,DEFAULT_SCHEMA:()=>DEFAULT_SCHEMA,CORE_SCHEMA:()=>CORE_SCHEMA});function isNothing(subject){return typeof subject>"u"||subject===null}function isObject(subject){return typeof subject==="object"&&subject!==null}function toArray(sequence){if(Array.isArray(sequence))return sequence;else if(isNothing(sequence))return[];return[sequence]}function extend(target,source){var index,length,key,sourceKeys;if(source){sourceKeys=Object.keys(source);for(index=0,length=sourceKeys.length;index<length;index+=1)key=sourceKeys[index],target[key]=source[key]}return target}function repeat(string,count){var result2="",cycle;for(cycle=0;cycle<count;cycle+=1)result2+=string;return result2}function isNegativeZero(number){return number===0&&Number.NEGATIVE_INFINITY===1/number}function formatError(exception,compact){var where="",message=exception.reason||"(unknown reason)";if(!exception.mark)return message;if(exception.mark.name)where+='in "'+exception.mark.name+'" ';if(where+="("+(exception.mark.line+1)+":"+(exception.mark.column+1)+")",!compact&&exception.mark.snippet)where+=`
515
522
 
516
523
  `+exception.mark.snippet;return message+" "+where}function YAMLException$1(reason,mark){if(Error.call(this),this.name="YAMLException",this.reason=reason,this.mark=mark,this.message=formatError(this,!1),Error.captureStackTrace)Error.captureStackTrace(this,this.constructor);else this.stack=Error().stack||""}function getLine(buffer2,lineStart,lineEnd,position,maxLineLength){var head="",tail="",maxHalfLength=Math.floor(maxLineLength/2)-1;if(position-lineStart>maxHalfLength)head=" ... ",lineStart=position-maxHalfLength+head.length;if(lineEnd-position>maxHalfLength)tail=" ...",lineEnd=position+maxHalfLength-tail.length;return{str:head+buffer2.slice(lineStart,lineEnd).replace(/\t/g,"\u2192")+tail,pos:position-lineStart+head.length}}function padStart(string,max){return common2.repeat(" ",max-string.length)+string}function makeSnippet(mark,options){if(options=Object.create(options||null),!mark.buffer)return null;if(!options.maxLength)options.maxLength=79;if(typeof options.indent!=="number")options.indent=1;if(typeof options.linesBefore!=="number")options.linesBefore=3;if(typeof options.linesAfter!=="number")options.linesAfter=2;var re=/\r?\n|\r|\0/g,lineStarts=[0],lineEnds=[],match,foundLineNo=-1;while(match=re.exec(mark.buffer))if(lineEnds.push(match.index),lineStarts.push(match.index+match[0].length),mark.position<=match.index&&foundLineNo<0)foundLineNo=lineStarts.length-2;if(foundLineNo<0)foundLineNo=lineStarts.length-1;var result2="",i,line,lineNoLength=Math.min(mark.line+options.linesAfter,lineEnds.length).toString().length,maxLineLength=options.maxLength-(options.indent+lineNoLength+3);for(i=1;i<=options.linesBefore;i++){if(foundLineNo-i<0)break;line=getLine(mark.buffer,lineStarts[foundLineNo-i],lineEnds[foundLineNo-i],mark.position-(lineStarts[foundLineNo]-lineStarts[foundLineNo-i]),maxLineLength),result2=common2.repeat(" ",options.indent)+padStart((mark.line-i+1).toString(),lineNoLength)+" | "+line.str+`
@@ -635,10 +642,13 @@ ${bin} set-option -w pane-active-border-style "fg=$COLOR"
635
642
  `,added}async function fireAgent(teamName,agentName){let config=await getTeam(teamName);if(!config)throw Error(`Team "${teamName}" not found.`);let idx=config.members.indexOf(agentName);if(idx===-1)return!1;config.members.splice(idx,1),await(await getConnection())`
636
643
  UPDATE teams SET members = ${JSON.stringify(config.members)}
637
644
  WHERE name = ${teamName}
638
- `;try{await killWorkersByName(agentName)}catch{}return!0}async function removeWorktree(worktreePath){if(!worktreePath||!existsSync21(worktreePath))return;try{await $3`git worktree remove --force ${worktreePath}`.quiet()}catch{try{await rm2(worktreePath,{recursive:!0,force:!0})}catch{}}}async function cleanupTeamTmuxSession(tmuxSessionName,teamName){if(!tmuxSessionName)return;try{if(!await findSessionByName(tmuxSessionName))return;let windows=await listWindows(tmuxSessionName),teamWindow=await findWindowByName(tmuxSessionName,teamName);if(tmuxSessionName===teamName||windows.length===1&&windows[0]?.name===teamName)await killSession(tmuxSessionName);else if(teamWindow)await executeTmux2(`kill-window -t '${teamWindow.id}'`)}catch{}}async function archiveTeam(teamName){let config=await getTeam(teamName);if(!config)return!1;let killResults=await Promise.allSettled(config.members.map((member)=>killWorkersByName(member,teamName)));for(let i2=0;i2<killResults.length;i2++)if(killResults[i2].status==="rejected")console.error(` Failed to kill member "${config.members[i2]}": ${killResults[i2].reason}`);if(await cleanupTeamTmuxSession(config.tmuxSessionName??teamName,teamName),(await(await getConnection())`
639
- UPDATE teams SET status = 'archived', archived_at = now(), updated_at = now()
640
- WHERE name = ${teamName}
641
- `).count===0)return!1;return recordAuditEvent("team",teamName,"archived",getActor(),{repo:config.repo}).catch(()=>{}),!0}async function unarchiveTeam(teamName){let config=await getTeam(teamName);if(!config)return!1;let restoredStatus="done";if((await(await getConnection())`
645
+ `;try{await killWorkersByName(agentName)}catch{}return!0}async function removeWorktree(worktreePath){if(!worktreePath||!existsSync21(worktreePath))return;try{await $3`git worktree remove --force ${worktreePath}`.quiet()}catch{try{await rm2(worktreePath,{recursive:!0,force:!0})}catch{}}}async function cleanupTeamTmuxSession(tmuxSessionName,teamName){if(!tmuxSessionName)return;try{if(!await findSessionByName(tmuxSessionName))return;let windows=await listWindows(tmuxSessionName),teamWindow=await findWindowByName(tmuxSessionName,teamName);if(tmuxSessionName===teamName||windows.length===1&&windows[0]?.name===teamName)await killSession(tmuxSessionName);else if(teamWindow)await executeTmux2(`kill-window -t '${teamWindow.id}'`)}catch{}}async function archiveTeam(teamName){let config=await getTeam(teamName);if(!config)return!1;let killResults=await Promise.allSettled(config.members.map((member)=>killWorkersByName(member,teamName)));for(let i2=0;i2<killResults.length;i2++)if(killResults[i2].status==="rejected")console.error(` Failed to kill member "${config.members[i2]}": ${killResults[i2].reason}`);await cleanupTeamTmuxSession(config.tmuxSessionName??teamName,teamName);let sql=await getConnection(),archivedAgents=0,updated=!1;if(await sql.begin(async(tx)=>{if((await tx`
646
+ UPDATE teams SET status = 'archived', archived_at = now(), updated_at = now()
647
+ WHERE name = ${teamName}
648
+ `).count===0)return;updated=!0,archivedAgents=(await tx`
649
+ UPDATE agents SET state = 'archived', updated_at = now()
650
+ WHERE team = ${teamName} AND state IS DISTINCT FROM 'archived'
651
+ `).count??0}),!updated)return!1;return recordAuditEvent("team",teamName,"archived",getActor(),{repo:config.repo,archivedAgents}).catch(()=>{}),!0}async function unarchiveTeam(teamName){let config=await getTeam(teamName);if(!config)return!1;let restoredStatus="done";if((await(await getConnection())`
642
652
  UPDATE teams SET status = ${restoredStatus}, archived_at = NULL, updated_at = now()
643
653
  WHERE name = ${teamName}
644
654
  `).count===0)return!1;return recordAuditEvent("team",teamName,"unarchived",getActor(),{repo:config.repo,restoredStatus}).catch(()=>{}),!0}async function disbandTeam(teamName){let config=await getTeam(teamName);if(!config)return!1;try{await deleteNativeTeam(teamName)}catch{}for(let member of config.members)try{await killWorkersByName(member,teamName)}catch{}await removeWorktree(config.worktreePath),await cleanupTeamTmuxSession(config.tmuxSessionName??teamName,teamName);let sql=await getConnection(),disbanded=!1;if(await sql.begin(async(tx)=>{if(config.wishSlug)try{let wishFile=`.genie/wishes/${config.wishSlug}/WISH.md`,parent=await tx`
@@ -647,10 +657,13 @@ ${bin} set-option -w pane-active-border-style "fg=$COLOR"
647
657
  LIMIT 1
648
658
  `;if(parent.length>0){let parentId=parent[0].id,inProgress=await tx`
649
659
  SELECT id FROM tasks WHERE parent_id = ${parentId} AND status = 'in_progress'
650
- `;if(inProgress.length>0){let ids=inProgress.map((r)=>r.id);await tx`UPDATE tasks SET status = 'ready', started_at = NULL, updated_at = now() WHERE id = ANY(${ids})`,await tx`DELETE FROM task_actors WHERE task_id = ANY(${ids}) AND role = 'assignee'`,console.log(` Reset ${ids.length} in-progress group(s) for wish "${config.wishSlug}"`)}}}catch{}disbanded=(await tx`
660
+ `;if(inProgress.length>0){let ids=inProgress.map((r)=>r.id);await tx`UPDATE tasks SET status = 'ready', started_at = NULL, updated_at = now() WHERE id = ANY(${ids})`,await tx`DELETE FROM task_actors WHERE task_id = ANY(${ids}) AND role = 'assignee'`,console.log(` Reset ${ids.length} in-progress group(s) for wish "${config.wishSlug}"`)}}}catch{}if(disbanded=(await tx`
651
661
  UPDATE teams SET status = 'archived', archived_at = now(), updated_at = now()
652
662
  WHERE name = ${teamName}
653
- `).count>0}),!disbanded)return!1;return recordAuditEvent("team",teamName,"disbanded",getActor(),{repo:config.repo}).catch(()=>{}),await pruneStaleWorktrees(config.repo),!0}async function pruneStaleWorktrees(_repoPath){let sql=await getConnection(),rows=await sql`SELECT name, worktree_path FROM teams`;for(let row of rows)if(row.worktree_path&&!existsSync21(row.worktree_path)){try{await deleteNativeTeam(row.name)}catch{}await sql`DELETE FROM teams WHERE name = ${row.name}`}}async function updateTeamConfig(name,config){await(await getConnection())`
663
+ `).count>0,disbanded)await tx`
664
+ UPDATE agents SET state = 'archived', updated_at = now()
665
+ WHERE team = ${teamName} AND state IS DISTINCT FROM 'archived'
666
+ `}),!disbanded)return!1;return recordAuditEvent("team",teamName,"disbanded",getActor(),{repo:config.repo}).catch(()=>{}),await pruneStaleWorktrees(config.repo),!0}async function pruneStaleWorktrees(_repoPath){let sql=await getConnection(),rows=await sql`SELECT name, worktree_path FROM teams`;for(let row of rows)if(row.worktree_path&&!existsSync21(row.worktree_path)){try{await deleteNativeTeam(row.name)}catch{}await sql`DELETE FROM teams WHERE name = ${row.name}`}}async function updateTeamConfig(name,config){await(await getConnection())`
654
667
  UPDATE teams SET
655
668
  repo = ${config.repo},
656
669
  base_branch = ${config.baseBranch},
@@ -1310,7 +1323,26 @@ Stopping inbox watcher...`),stopInboxWatcher2(handle),process.exit(0)};process.o
1310
1323
  INSERT INTO task_actors (task_id, actor_type, actor_id, role)
1311
1324
  VALUES (${child.id}, 'local', ${assignee}, 'assignee')
1312
1325
  ON CONFLICT (task_id, actor_type, actor_id, role) DO UPDATE SET created_at = now()
1313
- `,{status:"in_progress",assignee,dependsOn:deps.map((d)=>d.group_name),startedAt:now.toISOString()}}async function completeGroup(slug,groupName,cwd){let sql=await getConnection(),repoPath=resolveRepoPath(cwd),parent=await findParent(sql,slug,repoPath);if(!parent)throw Error(`Group "${groupName}" not found in wish "${slug}"`);let child=await findGroup(sql,parent.id,groupName);if(!child)throw Error(`Group "${groupName}" not found in wish "${slug}"`);if(child.status!=="in_progress")throw Error(`Cannot complete group "${groupName}": must be in_progress (currently ${child.status})`);let now=new Date;await sql`
1326
+ `,{status:"in_progress",assignee,dependsOn:deps.map((d)=>d.group_name),startedAt:now.toISOString()}}async function completeGroup(slug,groupName,cwd){let sql=await getConnection(),repoPath=resolveRepoPath(cwd),parent=await findParent(sql,slug,repoPath);if(!parent)throw Error(`Group "${groupName}" not found in wish "${slug}"`);let child=await findGroup(sql,parent.id,groupName);if(!child)throw Error(`Group "${groupName}" not found in wish "${slug}"`);if(child.status==="done"){let[actors2,deps2]=await Promise.all([sql`
1327
+ SELECT actor_id FROM task_actors WHERE task_id = ${child.id} AND role = 'assignee' LIMIT 1
1328
+ `,sql`
1329
+ SELECT t.group_name FROM task_dependencies td
1330
+ JOIN tasks t ON t.id = td.depends_on_id
1331
+ WHERE td.task_id = ${child.id}
1332
+ `]);return{status:"done",assignee:actors2.length>0?actors2[0].actor_id:void 0,dependsOn:deps2.map((d)=>d.group_name),startedAt:toISO(child.started_at),completedAt:toISO(child.ended_at)??toISO(child.updated_at)}}if(child.status==="blocked"){let blockers=(await sql`
1333
+ SELECT t.group_name, t.status
1334
+ FROM task_dependencies td
1335
+ JOIN tasks t ON t.id = td.depends_on_id
1336
+ WHERE td.task_id = ${child.id}
1337
+ AND t.status != 'done'
1338
+ `).map((d)=>`${d.group_name} (${d.status})`).join(", ");throw Error(`Cannot complete group "${groupName}": blocked on unmet dependencies: ${blockers||"unknown"}`)}if(child.status==="ready"){let assignee=process.env.GENIE_AGENT_NAME||"auto-recovered",startNow=new Date;if(await sql`
1339
+ UPDATE tasks SET status = 'in_progress', started_at = COALESCE(started_at, ${startNow}), updated_at = ${startNow}
1340
+ WHERE id = ${child.id}
1341
+ `,await sql`
1342
+ INSERT INTO task_actors (task_id, actor_type, actor_id, role)
1343
+ VALUES (${child.id}, 'local', ${assignee}, 'assignee')
1344
+ ON CONFLICT (task_id, actor_type, actor_id, role) DO UPDATE SET created_at = now()
1345
+ `,console.warn(`\u26A0 Group "${groupName}" was \`ready\` (dispatch-bypass); auto-transitioned to \`in_progress\` before completion.`),child.status="in_progress",!child.started_at)child.started_at=startNow}if(child.status!=="in_progress")throw Error(`Cannot complete group "${groupName}": must be in_progress (currently ${child.status})`);let now=new Date;await sql`
1314
1346
  UPDATE tasks SET status = 'done', ended_at = ${now}, updated_at = ${now}
1315
1347
  WHERE id = ${child.id}
1316
1348
  `,await sql`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automagik/genie",
3
- "version": "4.260420.9",
3
+ "version": "4.260420.10",
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": "4.260420.9",
3
+ "version": "4.260420.10",
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"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genie-plugin",
3
- "version": "4.260420.9",
3
+ "version": "4.260420.10",
4
4
  "private": true,
5
5
  "description": "Runtime dependencies for genie bundled CLIs",
6
6
  "type": "module",
@@ -87,7 +87,7 @@ genie team hire qa # for QA loop on dev
87
87
  - Same-layer wishes dispatch in parallel.
88
88
  - Dispatch workers via `genie work <agent> <slug>#<group>` — gets state tracking for free.
89
89
  - Parallel groups within a wish dispatched simultaneously.
90
- 3. Monitor via `genie task status <slug>`. Mark groups done via `genie task done <ref>`.
90
+ 3. Monitor via `genie wish status <slug>`. Mark groups done via `genie wish done <slug>#<group>` (and, when PG tasks exist, `genie task done #<seq>`).
91
91
  4. **Track progress (v4):** as each wish starts execution, move its child task:
92
92
  ```bash
93
93
  genie task move #<wish-seq> --to build --comment "Execution started"
@@ -192,4 +192,4 @@ When PG is available, the dream run is fully tracked in the task system:
192
192
  - Do not expand scope beyond what WISH.md defines.
193
193
  - Always write DREAM-REPORT.md, even if all wishes BLOCKED.
194
194
  - Poll CI status instead of sleeping — never use `sleep` in CI retry loops.
195
- - Use `genie task done`, `genie task status`, and `genie reset` for state tracking.
195
+ - Use `genie wish done`, `genie wish status`, and `genie wish reset` for wish-group state; use `genie task …` subcommands for PG task tracking. The two namespaces are distinct — do not substitute one for the other.
@@ -74,14 +74,23 @@ Then invoke the skill using the Skill tool, or run the command via Bash.
74
74
 
75
75
  ## Operational Command Mapping
76
76
 
77
- When the user's intent is **operational**, map natural language to genie CLI commands:
77
+ When the user's intent is **operational**, map natural language to genie CLI commands. **The CLI has two distinct lifecycle namespaces — don't confuse them:**
78
+
79
+ - **`genie wish …`** — wish-group state (progress, reset, done per `<slug>#<group>`). Source of truth for execution waves.
80
+ - **`genie task …`** — PG task lifecycle (checkout, move, comment, done per `#<seq>`). Source of truth for backlog + board.
78
81
 
79
82
  | User says | Command |
80
83
  |-----------|---------|
81
84
  | "check team status" / "how's the team" | `genie team ls` |
82
85
  | "spawn an engineer" / "start an engineer" | `genie spawn engineer` |
83
86
  | "list agents" / "show agents" | `genie ls` |
84
- | "show wish progress" / "status of [slug]" | `genie task status [slug]` |
87
+ | **"show wish progress" / "status of [slug]"** | **`genie wish status <slug>`** (NOT `genie task status` — that verb does not exist) |
88
+ | "mark wish group done" | `genie wish done <slug>#<group>` |
89
+ | "reset a stuck group" | `genie wish reset <slug>#<group>` |
90
+ | "list all wishes" | `genie wish list` |
91
+ | "show my tasks" / "backlog" | `genie task list` |
92
+ | "claim a task" / "start working on #N" | `genie task checkout #<seq>` |
93
+ | "mark task done" | `genie task done #<seq>` |
85
94
  | "kill agent X" / "stop X" | `genie kill X` or `genie stop X` |
86
95
  | "send message to X" | `genie send 'msg' --to X` |
87
96
  | "create a team for X" | `genie team create X --repo .` |
@@ -89,7 +98,29 @@ When the user's intent is **operational**, map natural language to genie CLI com
89
98
 
90
99
  ## CLI Commands (live)
91
100
 
92
- !`genie --help 2>/dev/null | head -50`
101
+ Top-level verb listing consult this on every session after `genie update` (see Rules):
102
+
103
+ !`genie --help 2>/dev/null`
104
+
105
+ ## Verb Anatomy (subcommand trees)
106
+
107
+ Top-level `--help` shows namespaces but hides their subcommands. These four namespaces carry 80% of orchestration traffic — re-read after any CLI version bump, because verbs migrate (`genie task status` → `genie wish status` happened in 4.260420.x).
108
+
109
+ ### `genie wish` — wish-group lifecycle
110
+
111
+ !`genie wish --help 2>/dev/null`
112
+
113
+ ### `genie task` — PG task lifecycle
114
+
115
+ !`genie task --help 2>/dev/null`
116
+
117
+ ### `genie team` — team lifecycle
118
+
119
+ !`genie team --help 2>/dev/null`
120
+
121
+ ### `genie agent` — agent lifecycle
122
+
123
+ !`genie agent --help 2>/dev/null`
93
124
 
94
125
  ## Reference
95
126
 
@@ -107,3 +138,5 @@ For questions about the wish lifecycle, skill descriptions, or how genie works,
107
138
  - For prompt refinement, suggest `/refine`.
108
139
  - NEVER use the Agent tool to spawn agents — use `genie spawn` instead.
109
140
  - NEVER use TeamCreate/TeamDelete — use `genie team create` / `genie team disband`.
141
+ - **Wish progress uses `genie wish status <slug>` — NOT `genie task status`.** The `task` subcommand has no `status` verb; it will error with `unknown command 'status'`. `genie task` is for PG tasks (`list`, `show`, `checkout`, `move`, `done`, `comment`, `block`).
142
+ - **After any `genie update` / version bump, re-read `genie wish --help` and `genie task --help` before typing yesterday's verbs.** Verb namespaces evolve (`genie done`, `genie wish done`, `genie task done` all exist and do different things). Muscle memory is a landmine; the live `--help` output in the sections above is the only source of truth.
@@ -39,7 +39,7 @@ This creates a git worktree, hires default agents (team-lead, engineer, reviewer
39
39
  ```bash
40
40
  genie team ls # List all teams
41
41
  genie team ls my-feature # Show team members
42
- genie task status my-feature-slug # Wish group progress
42
+ genie wish status my-feature-slug # Wish group progress
43
43
  genie agent log team-lead # Unified log
44
44
  genie agent log team-lead --raw # Raw pane output
45
45
  ```
@@ -69,8 +69,8 @@ The canonical hacks live in the docs at `genie/hacks.mdx`. Below is the embedded
69
69
  genie team create api-v2 --repo . --wish api-v2
70
70
 
71
71
  # Monitor both
72
- genie task status auth-refactor
73
- genie task status api-v2
72
+ genie wish status auth-refactor
73
+ genie wish status api-v2
74
74
 
75
75
  # Cross-team messaging
76
76
  genie agent send 'auth-refactor is done, you can proceed' --to api-v2-team-lead
@@ -227,7 +227,7 @@ The canonical hacks live in the docs at `genie/hacks.mdx`. Below is the embedded
227
227
 
228
228
  # Check team status
229
229
  genie team ls my-team
230
- genie task status my-wish-slug
230
+ genie wish status my-wish-slug
231
231
 
232
232
  # Unstick a blocked group
233
233
  genie wish reset my-wish-slug#2
@@ -342,8 +342,8 @@ genie team disband <name>
342
342
  ```bash
343
343
  genie agent spawn <role>
344
344
  genie work <slug>
345
- genie task status <slug>
346
- genie task done <slug>#<group>
345
+ genie wish status <slug>
346
+ genie wish done <slug>#<group>
347
347
  genie wish reset <slug>#<group>
348
348
  ```
349
349
 
@@ -368,7 +368,7 @@ genie task move #42 --to build
368
368
  genie team create rate-limiting --repo . --wish rate-limiting
369
369
 
370
370
  # 5. Monitor: track progress
371
- genie task status rate-limiting
371
+ genie wish status rate-limiting
372
372
  genie events summary --today
373
373
 
374
374
  # 6. Review: validate work
@@ -246,7 +246,7 @@ genie agent send 'Trace: genie work dispatches engineers but they start idle. Ch
246
246
 
247
247
  # 3. Capture evidence
248
248
  # Screenshot of idle engineer pane showing empty ❯ prompt
249
- # Output of: genie task status <slug> showing "in_progress" but no actual progress
249
+ # Output of: genie wish status <slug> showing "in_progress" but no actual progress
250
250
 
251
251
  # 4. Create GitHub issue with all findings
252
252
  gh issue create --title "bug: genie work dispatch — engineers spawn idle without initial task prompt" --body "$(cat <<'EOF'
@@ -259,7 +259,7 @@ protocolRouter.sendMessage fails silently under concurrent dispatch (4/6 enginee
259
259
 
260
260
  ## Evidence
261
261
  - [Screenshot: idle engineer pane]
262
- - genie task status shows in_progress but engineers at empty prompt
262
+ - genie wish status shows in_progress but engineers at empty prompt
263
263
  - Native inbox files: engineer-1 through engineer-4 have no dispatch message
264
264
 
265
265
  ## Steps to Reproduce
@@ -66,7 +66,7 @@ An engineer reports that `genie work` dispatches engineers but they sit idle. Th
66
66
  genie agent spawn tracer
67
67
 
68
68
  # 2. Send the symptoms
69
- genie agent send 'Trace: genie work dispatches engineers but they start idle at the prompt. No task received. genie task status shows in_progress but nothing happens. Check dispatch.ts workDispatchCommand and protocol-router.ts sendMessage.' --to tracer
69
+ genie agent send 'Trace: genie work dispatches engineers but they start idle at the prompt. No task received. genie wish status shows in_progress but nothing happens. Check dispatch.ts workDispatchCommand and protocol-router.ts sendMessage.' --to tracer
70
70
 
71
71
  # 3. Wait for findings
72
72
  sleep 60 && genie agent log tracer --raw
@@ -112,7 +112,7 @@ Depends-on: <group refs or "none">
112
112
  ## State Management
113
113
 
114
114
  - **Workers signal** completion via `genie agent send` to the leader when a group is done.
115
- - **Leader tracks** state via `genie task status <slug>` and marks groups complete via `genie task done <ref>`.
115
+ - **Leader tracks** wish-group state via `genie wish status <slug>` and marks groups complete via `genie wish done <slug>#<group>` (and, when PG tasks exist, `genie task done #<seq>`).
116
116
  - Workers do NOT call `genie task done` — that is the leader's responsibility after verifying the work.
117
117
  - If a group gets stuck, the leader can use `genie wish reset <ref>` to retry.
118
118
 
@@ -150,11 +150,11 @@ genie work fix-dispatch-initial-prompt
150
150
  # 🔧 Dispatching work to engineer for "fix-dispatch-initial-prompt#1"
151
151
 
152
152
  # 2. Monitor (ALWAYS sleep 60 between checks)
153
- sleep 60 && genie task status fix-dispatch-initial-prompt
153
+ sleep 60 && genie wish status fix-dispatch-initial-prompt
154
154
  # Output: Group 1: 🔄 in_progress
155
155
 
156
156
  # 3. Check again
157
- sleep 60 && genie task status fix-dispatch-initial-prompt
157
+ sleep 60 && genie wish status fix-dispatch-initial-prompt
158
158
  # Output: Group 1: ✅ done — Progress: 1/1 done
159
159
 
160
160
  # 4. All groups done → local review