@automagik/genie 4.260323.3 → 4.260323.4

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": "4.260323.3",
13
+ "version": "4.260323.4",
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
@@ -969,7 +969,7 @@ Done. ${results.length} migration${results.length===1?"":"s"} applied.`),await s
969
969
  (built-in ${resolved.entry.registeredAt==="(built-in)"?"agent":"agent"})`);console.log(""),printEntry(resolved.entry),console.log("")}async function listEntries(json2,includeBuiltins){let entries=await ls();if(json2){listEntriesJson(entries,includeBuiltins);return}if(entries.length===0&&!includeBuiltins){console.log(`
970
970
  No agents registered. Add one with: genie dir add <name> --dir <path>`),console.log(`Use --builtins to also see built-in roles and council members.
971
971
  `);return}if(entries.length>0)printRegisteredTable(entries);if(includeBuiltins)printBuiltinsTable()}function listEntriesJson(entries,includeBuiltins){let result=entries.map((e)=>({...e,builtin:!1}));if(includeBuiltins)for(let b2 of ALL_BUILTINS)result.push({name:b2.name,description:b2.description,model:b2.model,category:b2.category,scope:"built-in",builtin:!0});console.log(JSON.stringify(result,null,2))}function printRegisteredTable(entries){console.log(""),console.log("REGISTERED AGENTS"),console.log("-".repeat(85)),console.log(` ${"NAME".padEnd(22)}${"SCOPE".padEnd(10)}${"DIR".padEnd(30)}${"MODE".padEnd(8)}${"MODEL".padEnd(8)}ROLES`),console.log(` ${"-".repeat(20)} ${"-".repeat(8)} ${"-".repeat(28)} ${"-".repeat(6)} ${"-".repeat(6)} ${"-".repeat(15)}`);for(let entry of entries){let dir=contractPath(entry.dir),truncDir=dir.length>28?`${dir.slice(0,25)}...`:dir,roles=entry.roles?.join(", ")||"-";console.log(` ${entry.name.padEnd(22)}${entry.scope.padEnd(10)}${truncDir.padEnd(30)}${entry.promptMode.padEnd(8)}${(entry.model||"-").padEnd(8)}${roles}`)}console.log("")}function printBuiltinsTable(){console.log("BUILT-IN AGENTS"),console.log("-".repeat(80)),console.log(` ${"NAME".padEnd(22)}${"TYPE".padEnd(10)}${"MODEL".padEnd(8)}DESCRIPTION`),console.log(` ${"-".repeat(20)} ${"-".repeat(8)} ${"-".repeat(6)} ${"-".repeat(30)}`);for(let agent of ALL_BUILTINS)console.log(` ${agent.name.padEnd(22)}${agent.category.padEnd(10)}${(agent.model||"-").padEnd(8)}${agent.description}`);console.log("")}async function handleOmniRegistration(name,options){let omniUrl=await resolveOmniApiUrl();if(!omniUrl)return;console.log(`
972
- Registering in Omni (${omniUrl})...`);let existingId=await findOmniAgent(name);if(existingId){console.log(` Agent already exists in Omni: ${existingId}`),await edit(name,{omniAgentId:existingId},{global:options.global}),console.log(" Linked existing Omni agent to directory entry.");return}let omniAgentId=await registerAgentInOmni(name,{model:options.model,roles:options.roles});if(omniAgentId)await edit(name,{omniAgentId},{global:options.global}),console.log(` Omni agent created: ${omniAgentId}`),console.log(" Session isolation: per-person + per-channel")}async function handleAgentRegister(name,options){let promptMode=validatePromptMode(options.promptMode),entry=await add({name,dir:resolvePath(options.dir),repo:options.repo?resolvePath(options.repo):void 0,promptMode,model:options.model,roles:options.roles},{global:options.global}),scope=options.global?"global":"project";if(console.log(`Agent "${entry.name}" registered (${scope}).`),printEntry(entry),!options.skipOmni)await handleOmniRegistration(name,options)}function registerAgentNamespace(program2){program2.command("agent").description("Agent lifecycle management").command("register <name>").description("Register an agent locally and auto-register in Omni when configured").requiredOption("--dir <path>","Agent folder (CWD + AGENTS.md)").option("--repo <path>","Default git repo (overridden by team)").option("--prompt-mode <mode>","Prompt mode: append or system","append").option("--model <model>","Default model (sonnet, opus, codex)").option("--roles <roles...>","Built-in roles this agent can orchestrate").option("--global","Write to global directory instead of project").option("--skip-omni","Skip Omni auto-registration").action(async(name,options)=>{try{await handleAgentRegister(name,options)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}})}init_protocol_router();init_wish_state();init_agents();import{execSync as execSync6}from"child_process";import{existsSync as existsSync19}from"fs";import{mkdir as mkdir8,readFile as readFile9,writeFile as writeFile7}from"fs/promises";import{tmpdir}from"os";import{join as join24}from"path";init_wish_state();import{execSync as execSync5}from"child_process";import{existsSync as existsSync18}from"fs";import{readFile as readFile8}from"fs/promises";import{join as join23}from"path";function parseRef(ref){let hashIdx=ref.indexOf("#");if(hashIdx===-1)throw Error(`Invalid reference "${ref}". Expected format: <slug>#<group>`);let slug=ref.slice(0,hashIdx),group=ref.slice(hashIdx+1);if(!slug||!group)throw Error(`Invalid reference "${ref}". Both slug and group are required.`);return{slug,group}}var STATUS_ICONS={blocked:"\uD83D\uDD12",ready:"\uD83D\uDFE2",in_progress:"\uD83D\uDD04",done:"\u2705"};function formatTimestamp(iso){if(!iso)return"";return new Date(iso).toLocaleString("en-US",{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",hour12:!1})}function padRight2(str2,len){return str2.length>=len?str2:str2+" ".repeat(len-str2.length)}async function detectWaveCompletion(slug,groupName,cwd){let base=cwd??process.cwd(),wishPath=join23(base,".genie","wishes",slug,"WISH.md");if(!existsSync18(wishPath))return null;let content=await readFile8(wishPath,"utf-8"),targetWave=parseExecutionStrategy(content).find((w)=>w.groups.some((g)=>g.group===groupName));if(!targetWave)return null;let state2=await getState(slug,cwd);if(!state2)return null;let waveGroupNames=targetWave.groups.map((g)=>g.group);if(!waveGroupNames.every((g)=>state2.groups[g]?.status==="done"))return null;return{waveName:targetWave.name,waveGroups:waveGroupNames}}async function ensureWorkPushed(slug,group){try{if(execSync5("git status --porcelain",{encoding:"utf-8"}).trim())console.log(" Committing dirty working tree..."),execSync5("git add -A",{encoding:"utf-8"}),execSync5(`git commit -m "wip: ${slug}#${group}"`,{encoding:"utf-8"}),console.log(` Committed as "wip: ${slug}#${group}"`)}catch{}try{if(execSync5("git log @{u}..HEAD --oneline",{encoding:"utf-8"}).trim())console.log(" Pushing unpushed commits..."),execSync5("git push",{encoding:"utf-8",timeout:30000}),console.log(" Push complete.")}catch{try{let branch=execSync5("git rev-parse --abbrev-ref HEAD",{encoding:"utf-8"}).trim();if(branch&&branch!=="HEAD")execSync5(`git push -u origin ${branch}`,{encoding:"utf-8",timeout:30000}),console.log(" Push complete (set upstream).")}catch{console.log(" \u26A0\uFE0F Push failed \u2014 manual push may be needed.")}}}function autoKillPane(){let paneId=process.env.TMUX_PANE;if(paneId)setTimeout(()=>{try{execSync5(`tmux kill-pane -t '${paneId}'`,{encoding:"utf-8"})}catch{process.exit(0)}},1000);else process.exit(0)}async function doneCommand(ref){try{let{slug,group}=parseRef(ref),result=await completeGroup(slug,group);if(console.log(`\u2705 Group "${group}" marked as done in wish "${slug}"`),result.completedAt)console.log(` Completed at: ${formatTimestamp(result.completedAt)}`);let state2=await getState(slug);if(state2){let nowReady=Object.entries(state2.groups).filter(([,g])=>g.status==="ready"&&g.dependsOn.includes(group)).map(([name])=>name);if(nowReady.length>0)console.log(` Unblocked: ${nowReady.join(", ")}`)}await ensureWorkPushed(slug,group);let waveResult=await detectWaveCompletion(slug,group);if(waveResult){console.log(` \uD83C\uDF0A ${waveResult.waveName} complete! All groups done: ${waveResult.waveGroups.join(", ")}`);try{let protocolRouter=await Promise.resolve().then(() => (init_protocol_router(),exports_protocol_router)),repoPath=process.cwd(),message=`${waveResult.waveName} complete. All groups done: [${waveResult.waveGroups.join(", ")}]. Run /review or advance to next wave.`,result2=await protocolRouter.sendMessage(repoPath,"cli","team-lead",message);if(result2&&typeof result2==="object"&&"delivered"in result2&&!result2.delivered)console.warn(" \u26A0\uFE0F Wave-complete notification may not have been delivered.");else console.log(" Notified team-lead of wave completion.")}catch{console.warn(" \u26A0\uFE0F Could not notify team-lead (messaging unavailable).")}}autoKillPane()}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`\u274C ${message}`),process.exit(1)}}async function statusCommand(slug){try{let state2=await getState(slug);if(!state2)console.error(`\u274C No state found for wish "${slug}"`),console.error(" Initialize with: genie work <slug>"),process.exit(1);console.log(`
972
+ Registering in Omni (${omniUrl})...`);let existingId=await findOmniAgent(name);if(existingId){console.log(` Agent already exists in Omni: ${existingId}`),await edit(name,{omniAgentId:existingId},{global:options.global}),console.log(" Linked existing Omni agent to directory entry.");return}let omniAgentId=await registerAgentInOmni(name,{model:options.model,roles:options.roles});if(omniAgentId)await edit(name,{omniAgentId},{global:options.global}),console.log(` Omni agent created: ${omniAgentId}`),console.log(" Session isolation: per-person + per-channel")}async function handleAgentRegister(name,options){let promptMode=validatePromptMode(options.promptMode),entry=await add({name,dir:resolvePath(options.dir),repo:options.repo?resolvePath(options.repo):void 0,promptMode,model:options.model,roles:options.roles},{global:options.global}),scope=options.global?"global":"project";if(console.log(`Agent "${entry.name}" registered (${scope}).`),printEntry(entry),!options.skipOmni)await handleOmniRegistration(name,options)}function registerAgentNamespace(program2){program2.command("agent").description("Agent lifecycle management").command("register <name>").description("Register an agent locally and auto-register in Omni when configured").requiredOption("--dir <path>","Agent folder (CWD + AGENTS.md)").option("--repo <path>","Default git repo (overridden by team)").option("--prompt-mode <mode>","Prompt mode: append or system","append").option("--model <model>","Default model (sonnet, opus, codex)").option("--roles <roles...>","Built-in roles this agent can orchestrate").option("--global","Write to global directory instead of project").option("--skip-omni","Skip Omni auto-registration").action(async(name,options)=>{try{await handleAgentRegister(name,options)}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`Error: ${message}`),process.exit(1)}})}init_protocol_router();init_wish_state();init_agents();import{execSync as execSync6}from"child_process";import{existsSync as existsSync19}from"fs";import{mkdir as mkdir8,readFile as readFile9,writeFile as writeFile7}from"fs/promises";import{tmpdir}from"os";import{join as join24}from"path";init_wish_state();import{execSync as execSync5}from"child_process";import{existsSync as existsSync18}from"fs";import{readFile as readFile8}from"fs/promises";import{join as join23}from"path";function parseRef(ref){let hashIdx=ref.indexOf("#");if(hashIdx===-1)throw Error(`Invalid reference "${ref}". Expected format: <slug>#<group>`);let slug=ref.slice(0,hashIdx),group=ref.slice(hashIdx+1);if(!slug||!group)throw Error(`Invalid reference "${ref}". Both slug and group are required.`);return{slug,group}}var STATUS_ICONS={blocked:"\uD83D\uDD12",ready:"\uD83D\uDFE2",in_progress:"\uD83D\uDD04",done:"\u2705"};function formatTimestamp(iso){if(!iso)return"";return new Date(iso).toLocaleString("en-US",{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",hour12:!1})}function padRight2(str2,len){return str2.length>=len?str2:str2+" ".repeat(len-str2.length)}async function detectWaveCompletion(slug,groupName,cwd){let base=cwd??process.cwd(),wishPath=join23(base,".genie","wishes",slug,"WISH.md");if(!existsSync18(wishPath))return null;let content=await readFile8(wishPath,"utf-8"),targetWave=parseExecutionStrategy(content).find((w)=>w.groups.some((g)=>g.group===groupName));if(!targetWave)return null;let state2=await getState(slug,cwd);if(!state2)return null;let waveGroupNames=targetWave.groups.map((g)=>g.group);if(!waveGroupNames.every((g)=>state2.groups[g]?.status==="done"))return null;return{waveName:targetWave.name,waveGroups:waveGroupNames}}async function ensureWorkPushed(slug,group){try{if(execSync5("git status --porcelain",{encoding:"utf-8"}).trim())console.log(" Committing dirty working tree..."),execSync5("git add -A",{encoding:"utf-8"}),execSync5(`git commit -m "wip: ${slug}#${group}"`,{encoding:"utf-8"}),console.log(` Committed as "wip: ${slug}#${group}"`)}catch{}try{if(execSync5("git log @{u}..HEAD --oneline",{encoding:"utf-8"}).trim())console.log(" Pushing unpushed commits..."),execSync5("git push",{encoding:"utf-8",timeout:30000}),console.log(" Push complete.")}catch{try{let branch=execSync5("git rev-parse --abbrev-ref HEAD",{encoding:"utf-8"}).trim();if(branch&&branch!=="HEAD")execSync5(`git push -u origin ${branch}`,{encoding:"utf-8",timeout:30000}),console.log(" Push complete (set upstream).")}catch{console.log(" \u26A0\uFE0F Push failed \u2014 manual push may be needed.")}}}function autoKillPane(){let paneId=process.env.TMUX_PANE;if(paneId)setTimeout(()=>{try{execSync5(`tmux kill-pane -t '${paneId}'`,{encoding:"utf-8"})}catch{process.exit(0)}},1000);else process.exit(0)}async function doneCommand(ref){try{let{slug,group}=parseRef(ref),result=await completeGroup(slug,group);if(console.log(`\u2705 Group "${group}" marked as done in wish "${slug}"`),result.completedAt)console.log(` Completed at: ${formatTimestamp(result.completedAt)}`);let state2=await getState(slug);if(state2){let nowReady=Object.entries(state2.groups).filter(([,g])=>g.status==="ready"&&g.dependsOn.includes(group)).map(([name])=>name);if(nowReady.length>0)console.log(` Unblocked: ${nowReady.join(", ")}`)}await ensureWorkPushed(slug,group);let waveResult=await detectWaveCompletion(slug,group);if(waveResult){console.log(` \uD83C\uDF0A ${waveResult.waveName} complete! All groups done: ${waveResult.waveGroups.join(", ")}`);try{let protocolRouter=await Promise.resolve().then(() => (init_protocol_router(),exports_protocol_router)),repoPath=process.cwd(),message=`${waveResult.waveName} complete. All groups done: [${waveResult.waveGroups.join(", ")}]. Run /review or advance to next wave.`,result2=await protocolRouter.sendMessage(repoPath,"cli","team-lead",message);if(result2&&typeof result2==="object"&&"delivered"in result2&&!result2.delivered)console.warn(" \u26A0\uFE0F Wave-complete notification may not have been delivered.");else console.log(" Notified team-lead of wave completion.")}catch{console.warn(" \u26A0\uFE0F Could not notify team-lead (messaging unavailable).")}}autoKillPane()}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`\u274C ${message}`),process.exit(1)}}async function statusCommand(slug){try{let state2=await getState(slug);if(!state2)console.error(`\u274C No state found for wish "${slug}"`),console.error(" This means work has not been dispatched yet."),console.error(` Run: genie work ${slug}`),process.exit(1);console.log(`
973
973
  Wish: ${state2.wish}`),console.log("\u2500".repeat(60));let entries=Object.entries(state2.groups),maxNameLen=Math.max(...entries.map(([name])=>name.length),5);console.log(` ${padRight2("GROUP",maxNameLen)} STATUS ASSIGNEE STARTED COMPLETED`),console.log(` ${"\u2500".repeat(maxNameLen+62)}`);for(let[name,group]of entries){let icon=STATUS_ICONS[group.status]??"\u2753",status=padRight2(`${icon} ${group.status}`,13),assignee=padRight2(group.assignee??"-",13),started=padRight2(formatTimestamp(group.startedAt)||"-",14),completed=formatTimestamp(group.completedAt)||"-";console.log(` ${padRight2(name,maxNameLen)} ${status} ${assignee} ${started} ${completed}`)}let total=entries.length,done=entries.filter(([,g])=>g.status==="done").length,inProgress=entries.filter(([,g])=>g.status==="in_progress").length,ready=entries.filter(([,g])=>g.status==="ready").length,blocked=entries.filter(([,g])=>g.status==="blocked").length;console.log(""),console.log(` Progress: ${done}/${total} done | ${inProgress} in progress | ${ready} ready | ${blocked} blocked`),console.log("")}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`\u274C ${message}`),process.exit(1)}}function registerStateCommands(program2){program2.command("done <ref>").description("Mark a wish group as done (format: <slug>#<group>)").action(async(ref)=>{await doneCommand(ref)}),program2.command("status <slug>").description("Show wish state overview for all groups").action(async(slug)=>{await statusCommand(slug)}),program2.command("reset <ref>").description("Reset an in-progress group back to ready (format: <slug>#<group>)").action(async(ref)=>{try{let{slug,group}=parseRef(ref),result=await resetGroup(slug,group);if(console.log(`\uD83D\uDD04 Group "${group}" reset to ready in wish "${slug}"`),result.status==="ready")console.log(" Status: ready (assignee cleared)")}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(`\u274C ${message}`),process.exit(1)}})}async function writeContextFile(content){let dir=join24(tmpdir(),"genie-dispatch");await mkdir8(dir,{recursive:!0});let ts=Date.now().toString(36),rand=Math.random().toString(36).slice(2,8),filePath=join24(dir,`ctx-${ts}-${rand}.md`);return await writeFile7(filePath,content),filePath}function extractGroup(content,groupName){let pattern=new RegExp(`^### Group ${escapeRegExp(groupName)}:`,"m"),match=content.match(pattern);if(!match||match.index===void 0)return null;let start=match.index,nextBoundary=content.slice(start).slice(1).search(/^### Group \d|^---$/m),end=nextBoundary!==-1?start+1+nextBoundary:content.length;return content.slice(start,end).trim()}function extractWishContext(content){let execGroupsIdx=content.indexOf("## Execution Groups");if(execGroupsIdx!==-1)return content.slice(0,execGroupsIdx).trim();return content.slice(0,2000).trim()}function escapeRegExp(str2){return str2.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function buildContextPrompt(opts){let parts=[`# Dispatch Context (${opts.command})`,"",`**Source file:** \`${opts.filePath}\``,"(Read the full document at the path above for complete context)",""];if(opts.wishContext)parts.push("## Wish Context","",opts.wishContext,"");if(parts.push("## Assigned Section","",opts.sectionContent,""),opts.skill)parts.push("## Initial Command","",`Run \`/${opts.skill}\` to begin.`,"");return parts.join(`
974
974
  `)}function getGitDiff(){try{let diff=execSync6("git diff HEAD",{encoding:"utf-8",maxBuffer:1048576}),staged=execSync6("git diff --cached",{encoding:"utf-8",maxBuffer:1048576}),combined=[diff,staged].filter(Boolean).join(`
975
975
  `);if(combined.length>50000)return`${combined.slice(0,50000)}
@@ -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": "4.260323.3",
5
+ "version": "4.260323.4",
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": "4.260323.3",
3
+ "version": "4.260323.4",
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.260323.3",
3
+ "version": "4.260323.4",
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"
@@ -68,4 +68,5 @@ Never rely on messages alone to determine completion. Always check `genie status
68
68
  - NEVER push to main or master.
69
69
  - NEVER use the Agent tool.
70
70
  - NEVER run `genie status`, `genie ls`, or `genie inbox` before Phase 2.
71
+ - If you ran `genie status` and got "No state found", this means work has NOT been dispatched. Go to Phase 2 immediately and run `genie work <slug>`. Do NOT poll or wait.
71
72
  </constraints>
@@ -16,6 +16,9 @@ genie status <slug>
16
16
  ```
17
17
  Which groups are done? Which are in progress? Which are blocked?
18
18
 
19
+ If `genie status` returns "No state found", work was never dispatched.
20
+ Run `genie work <slug>` to initialize and dispatch — do NOT poll.
21
+
19
22
  ### 3. Check Workers
20
23
  ```bash
21
24
  genie ls
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genie-plugin",
3
- "version": "4.260323.3",
3
+ "version": "4.260323.4",
4
4
  "private": true,
5
5
  "description": "Runtime dependencies for genie bundled CLIs",
6
6
  "type": "module",
@@ -238,7 +238,8 @@ export async function statusCommand(slug: string): Promise<void> {
238
238
  const state = await wishState.getState(slug);
239
239
  if (!state) {
240
240
  console.error(`❌ No state found for wish "${slug}"`);
241
- console.error(' Initialize with: genie work <slug>');
241
+ console.error(' This means work has not been dispatched yet.');
242
+ console.error(` Run: genie work ${slug}`);
242
243
  process.exit(1);
243
244
  }
244
245