@automagik/genie 4.260402.4 → 4.260402.6

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.260402.4",
13
+ "version": "4.260402.6",
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
@@ -2292,7 +2292,7 @@ Board: ${board.name} (${board.id})`),board.description)console.log(`Description:
2292
2292
  Columns:`);for(let i2=0;i2<sorted.length;i2++){let c=sorted[i2],count=countByColumn.get(c.name)??countByColumn.get(c.id)??0,gate=` [gate: ${c.gate}]`,action=c.action?` (action: ${c.action})`:"";console.log(` ${i2+1}. ${c.label??c.name}${gate}${action} \u2014 ${count} task${count===1?"":"s"}`)}console.log("")}function buildColumnUpdates(options){let updates={};if(options.gate)updates.gate=options.gate;if(options.action)updates.action=options.action;if(options.color)updates.color=options.color;if(options.rename)updates.name=options.rename,updates.label=options.rename;return updates}async function handleBoardEdit(name,options){let bs=await getBoardService(),board=await resolveBoard(name,options.project);if(options.column){let col=board.columns.find((c)=>c.name===options.column||c.label===options.column);if(!col)throw Error(`Column not found: ${options.column}`);let updates=buildColumnUpdates(options);if(!await bs.updateColumn(board.id,col.id,updates))throw Error(`Failed to update column: ${options.column}`);console.log(`Updated column "${options.column}" on board "${board.name}".`);return}let boardUpdates={};if(options.name)boardUpdates.name=options.name;if(options.description)boardUpdates.description=options.description;if(Object.keys(boardUpdates).length===0)console.error("Error: No updates specified. Use --column, --name, or --description."),process.exit(1);let updated=await bs.updateBoard(board.id,boardUpdates);if(!updated)throw Error(`Failed to update board: ${name}`);console.log(`Updated board "${updated.name}" (${updated.id}).`)}async function handleBoardDelete(name,options){let bs=await getBoardService(),board=await resolveBoard(name,options.project);if(!options.force)console.log(`Deleting board "${board.name}" (${board.id})...`);if(!await bs.deleteBoard(board.id))throw Error(`Failed to delete board: ${name}`);console.log(`Deleted board "${board.name}" (${board.id}).`)}async function handleBoardColumns(name,options){let board=await resolveBoard(name,options.project);if(options.json){console.log(JSON.stringify(board.columns,null,2));return}printColumnPipeline(board.columns,`Board: ${board.name} (${board.columns.length} columns)`)}async function handleBoardUse(name,options){let board=await resolveBoard(name,options.project),repoRoot=execSync8("git rev-parse --show-toplevel",{encoding:"utf-8"}).trim(),genieDir=join36(repoRoot,".genie"),configPath2=join36(genieDir,"config.json");if(!existsSync27(genieDir))mkdirSync12(genieDir,{recursive:!0});let config={};if(existsSync27(configPath2))try{config=JSON.parse(readFileSync14(configPath2,"utf-8"))}catch{}config.activeBoard=board.id,writeFileSync11(configPath2,`${JSON.stringify(config,null,2)}
2293
2293
  `),console.log(`Active board set to "${board.name}" (${board.id})`)}async function handleBoardExport(name,options){let bs=await getBoardService(),board=await resolveBoard(name,options.project),exported=await bs.exportBoard(board.id),json2=JSON.stringify(exported,null,2);if(options.output){let dir=dirname6(options.output);if(!existsSync27(dir))mkdirSync12(dir,{recursive:!0});writeFileSync11(options.output,`${json2}
2294
2294
  `),console.log(`Exported board "${board.name}" to ${options.output}`)}else console.log(json2)}async function handleBoardReconcile(name,options){let{reconcileBoard:reconcileBoard2}=await Promise.resolve().then(() => (init_board_service(),exports_board_service)),board=await resolveBoard(name,options.project),result=await reconcileBoard2(board.id);if(options.json){console.log(JSON.stringify(result,null,2));return}if(result.fixed===0&&result.orphaned===0){console.log(`Board "${board.name}": all tasks have valid column_ids.`);return}if(console.log(`Board "${board.name}" reconciliation:`),console.log(` Fixed: ${result.fixed} task${result.fixed===1?"":"s"}`),result.orphaned>0){let count=result.orphaned;console.log(` Still orphaned: ${count} task${count===1?"":"s"} (stage doesn't match any column)`)}}async function handleBoardImport(options){let bs=await getBoardService(),projectId=await resolveProjectId(options.project),raw=readFileSync14(options.json,"utf-8"),data=JSON.parse(raw),board=await bs.importBoard(data,projectId);console.log(`Imported board "${board.name}" (${board.id}) with ${board.columns.length} columns`)}async function handleTemplateList(options){let templates=await(await getTemplateService()).listTemplates();if(options.json){console.log(JSON.stringify(templates,null,2));return}printTemplateTable(templates)}async function handleTemplateShow(name,options){let template=await(await getTemplateService()).getTemplate(name);if(!template)throw Error(`Template not found: ${name}`);if(options.json){console.log(JSON.stringify(template,null,2));return}if(console.log(`
2295
- Template: ${template.name} (${template.id})`),template.description)console.log(`Description: ${template.description}`);if(template.icon)console.log(`Icon: ${template.icon}`);console.log(`Built-in: ${template.isBuiltin?"yes":"no"}`),printColumnPipeline(template.columns,`Pipeline (${template.columns.length} columns)`)}async function handleTemplateCreate(name,options){let tmpl=await getTemplateService();if(options.fromBoard){let board=await(await getBoardService()).getBoard(options.fromBoard);if(!board)throw Error(`Board not found: ${options.fromBoard}`);let template2=await tmpl.snapshotFromBoard(board.id,name);console.log(`Created template "${template2.name}" (${template2.id}) from board "${board.name}" with ${template2.columns.length} columns`);return}let columns;if(options.columns)columns=options.columns.split(",").map((colName,i2)=>({id:crypto.randomUUID(),name:colName.trim(),label:colName.trim(),gate:"human",action:null,auto_advance:!1,transitions:[],roles:["*"],color:"#94a3b8",parallel:!1,on_fail:null,position:i2}));let template=await tmpl.createTemplate({name,description:options.description,columns});console.log(`Created template "${template.name}" (${template.id}) with ${template.columns.length} columns`)}async function handleTemplateEdit(name,options){let tmpl=await getTemplateService(),template=await tmpl.getTemplate(name);if(!template)throw Error(`Template not found: ${name}`);if(!options.column)console.error("Error: --column is required for template edit."),process.exit(1);let updates={};if(options.gate)updates.gate=options.gate;if(options.action)updates.action=options.action;if(options.color)updates.color=options.color;if(options.rename)updates.name=options.rename,updates.label=options.rename;if(!await tmpl.updateTemplateColumn(template.id,options.column,updates))throw Error(`Failed to update template: ${name}`);console.log(`Updated column "${options.column}" on template "${template.name}".`)}async function handleTemplateRename(oldName,newName){let tmpl=await getTemplateService(),template=await tmpl.getTemplate(oldName);if(!template)throw Error(`Template not found: ${oldName}`);let updated=await tmpl.renameTemplate(template.id,newName);if(!updated)throw Error(`Failed to rename template: ${oldName}`);console.log(`Renamed template "${oldName}" to "${updated.name}".`)}async function handleTemplateDelete(name){let tmpl=await getTemplateService(),template=await tmpl.getTemplate(name);if(!template)throw Error(`Template not found: ${name}`);if(!await tmpl.deleteTemplate(template.id))throw Error(`Failed to delete template: ${name}`);console.log(`Deleted template "${template.name}" (${template.id}).`)}function registerBoardCommands(program2){let board=program2.command("board").description("Board and pipeline management");board.command("create <name>").description("Create a new board").option("--project <project>","Project name").option("--from <template>","Create from template name").option("--columns <columns>","Comma-separated column names").option("--description <text>","Board description").action(async(name,options)=>{try{await handleBoardCreate(name,options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("list").description("List all boards").option("--project <project>","Filter by project").option("--all","Include archived boards").option("--json","Output as JSON").action(async(options)=>{try{await handleBoardList(options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("show <name...>").description("Show board detail").option("--project <project>","Disambiguate by project").option("--json","Output as JSON").action(async(nameParts,options)=>{try{await handleBoardShow(nameParts.join(" "),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("edit <name...>").description("Edit board or column properties").option("--project <project>","Disambiguate by project").option("--column <col>","Column name to edit").option("--gate <gate>","New gate value (human|agent|human+agent)").option("--action <action>","New action skill").option("--color <color>","New color hex").option("--rename <new>","Rename the column").option("--name <new>","Rename the board itself").option("--description <text>","Update description").action(async(nameParts,options)=>{try{await handleBoardEdit(nameParts.join(" "),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("delete <name...>").description("Delete a board").option("--project <project>","Disambiguate by project").option("--force","Skip confirmation").action(async(nameParts,options)=>{try{await handleBoardDelete(nameParts.join(" "),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("columns <name...>").description("Show board column pipeline").option("--project <project>","Disambiguate by project").option("--json","Output as JSON").action(async(nameParts,options)=>{try{await handleBoardColumns(nameParts.join(" "),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("use <name...>").description("Set active board for current repo").option("--project <project>","Disambiguate by project").action(async(nameParts,options)=>{try{await handleBoardUse(nameParts.join(" "),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("export <name...>").description("Export board as JSON").option("--project <project>","Disambiguate by project").option("--output <file>","Write to file instead of stdout").option("--json","Output as JSON (default, accepted for consistency)").action(async(nameParts,options)=>{try{await handleBoardExport(nameParts.join(" "),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("reconcile <name...>").description("Fix orphaned column_ids by matching task stage to board columns").option("--project <project>","Disambiguate by project").option("--json","Output as JSON").action(async(nameParts,options)=>{try{await handleBoardReconcile(nameParts.join(" "),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("archive <name...>").description("Archive a board and its unfinished tasks").option("--project <project>","Disambiguate by project").action(async(nameParts,options)=>{try{let ts3=await getTaskService3(),board2=await resolveBoard(nameParts.join(" "),options.project);await ts3.archiveBoard(board2.id),console.log(`Archived board "${board2.name}" and its unfinished tasks.`)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("import").description("Import board from JSON file").requiredOption("--json <file>","JSON file to import").requiredOption("--project <project>","Target project").action(async(options)=>{try{await handleBoardImport(options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}});let template=board.command("template").description("Board template management");template.command("list").description("List all board templates").option("--json","Output as JSON").action(async(options)=>{try{await handleTemplateList(options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),template.command("show <name>").description("Show template detail with pipeline view").option("--json","Output as JSON").action(async(name,options)=>{try{await handleTemplateShow(name,options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),template.command("create <name>").description("Create a board template").option("--from-board <board>","Create from existing board").option("--columns <columns>","Comma-separated column names").option("--description <text>","Template description").action(async(name,options)=>{try{await handleTemplateCreate(name,options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),template.command("edit <name>").description("Edit a template column").option("--column <col>","Column name to edit").option("--gate <gate>","New gate value (human|agent|human+agent)").option("--action <action>","New action skill").option("--rename <new>","Rename the column").option("--color <color>","New color hex").action(async(name,options)=>{try{await handleTemplateEdit(name,options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),template.command("rename <old> <new>").description("Rename a template").action(async(oldName,newName)=>{try{await handleTemplateRename(oldName,newName)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),template.command("delete <name>").description("Delete a template").action(async(name)=>{try{await handleTemplateDelete(name)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}})}import{execSync as execSync9}from"child_process";var BRAIN_PKG="@automagik/genie-brain",BRAIN_REGISTRY="https://npm.pkg.github.com",BRAIN_SCOPE="@automagik";async function installBrain(){console.log(""),console.log(" Installing @automagik/genie-brain (enterprise)..."),console.log("");try{execSync9(`npm config set ${BRAIN_SCOPE}:registry ${BRAIN_REGISTRY}`,{stdio:"inherit"});let hasToken=!1;try{let rc=execSync9(`npm config get //${BRAIN_REGISTRY.replace("https://","")}/:_authToken`,{encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim();hasToken=rc.length>0&&rc!=="undefined"}catch{}if(!hasToken)return console.log(" GitHub Packages requires authentication."),console.log(" Set your token:"),console.log(""),console.log(' echo "//npm.pkg.github.com/:_authToken=YOUR_GITHUB_TOKEN" >> ~/.npmrc'),console.log(""),console.log(" Generate a token at: https://github.com/settings/tokens"),console.log(" Required scope: read:packages"),console.log(""),!1;execSync9(`bun add ${BRAIN_PKG}`,{stdio:"inherit"}),console.log(""),console.log(" \u2713 Brain installed successfully."),console.log("");try{let brain=await import(BRAIN_PKG);if(brain.runAllMigrations)console.log(" Running brain migrations..."),await brain.runAllMigrations(),console.log(" \u2713 Brain tables created in Postgres.")}catch{console.log(" \u26A0 Auto-migration skipped. Run: genie brain migrate")}return console.log(""),console.log(" Get started:"),console.log(" genie brain init --name my-brain --path ./brain"),console.log(""),!0}catch(err){let msg=err instanceof Error?err.message:String(err);return console.error(` \u2717 Install failed: ${msg}`),console.log(""),console.log(" Manual install:"),console.log(` npm config set ${BRAIN_SCOPE}:registry ${BRAIN_REGISTRY}`),console.log(` bun add ${BRAIN_PKG}`),console.log(""),!1}}function uninstallBrain(){try{execSync9(`bun remove ${BRAIN_PKG}`,{stdio:"inherit"}),console.log(" \u2713 Brain uninstalled.")}catch{console.error(" Uninstall failed. Manual: bun remove @automagik/genie-brain")}}function isModuleNotFound(msg){return msg.includes("Cannot find")||msg.includes("not found")||msg.includes("MODULE_NOT_FOUND")}function printNotInstalledMessage(){console.log(""),console.log(" Brain is an enterprise knowledge graph engine."),console.log(" It is not installed."),console.log(""),console.log(" Quick install:"),console.log(""),console.log(" genie brain install"),console.log(""),console.log(" Requires GitHub org membership (automagik-dev)."),console.log("")}async function executeBrainCommand(args){try{let brain=await import(BRAIN_PKG);if(brain.execute)await brain.execute(args);else console.error("Brain module loaded but execute() not found."),console.error("Update: bun add @automagik/genie-brain@latest")}catch(err){let msg=err instanceof Error?err.message:String(err);if(isModuleNotFound(msg))printNotInstalledMessage();else console.error(`Brain error: ${msg}`)}}function registerBrainCommands(program2){program2.command("brain").description("Knowledge graph engine (enterprise)").allowUnknownOption().allowExcessArguments().action(async(_options,cmd)=>{let args=cmd.args;if(args[0]==="install"){await installBrain();return}if(args[0]==="uninstall"){uninstallBrain();return}await executeBrainCommand(args)})}var _brief2;async function getBrief2(){if(!_brief2)_brief2=await Promise.resolve().then(() => (init_brief(),exports_brief));return _brief2}async function handleBrief2(options){let team=options.team??process.env.GENIE_TEAM;if(!team)console.error("Error: --team is required (or set GENIE_TEAM)"),process.exit(1);let agent=options.agent??process.env.GENIE_AGENT_NAME,briefService=await getBrief2(),brief=await briefService.generateBrief({team,agent,since:options.since,repoPath:process.cwd()});console.log(briefService.formatBrief(brief))}function registerBriefCommands(program2){program2.command("brief").description("Show startup brief \u2014 aggregated context since last session").option("--team <name>","Team name (default: GENIE_TEAM)").option("--agent <name>","Agent name (default: GENIE_AGENT_NAME)").option("--since <iso>","Start timestamp (default: last executor end)").action(async(options)=>{try{await handleBrief2(options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}})}import{existsSync as existsSync28,mkdirSync as mkdirSync13,readFileSync as readFileSync15,unlinkSync as unlinkSync7,writeFileSync as writeFileSync12}from"fs";import{homedir as homedir25}from"os";import{join as join37}from"path";function genieHome3(){return process.env.GENIE_HOME??join37(homedir25(),".genie")}function pidFilePath(){return join37(genieHome3(),"scheduler.pid")}function logFilePath(){return join37(genieHome3(),"logs","scheduler.log")}function systemdDir(){return join37(homedir25(),".config","systemd","user")}function systemdUnitPath(){return join37(systemdDir(),"genie-scheduler.service")}function readPid(){let path2=pidFilePath();if(!existsSync28(path2))return null;let raw=readFileSync15(path2,"utf-8").trim(),pid=Number.parseInt(raw,10);if(Number.isNaN(pid)||pid<=0)return null;return pid}function writePid(pid){let dir=genieHome3();mkdirSync13(dir,{recursive:!0}),writeFileSync12(pidFilePath(),String(pid),"utf-8")}function removePid(){let path2=pidFilePath();if(existsSync28(path2))try{unlinkSync7(path2)}catch{}}function isProcessAlive2(pid){try{return process.kill(pid,0),!0}catch{return!1}}function generateSystemdUnit(){let genieBin=process.argv[1]??"genie";return`[Unit]
2295
+ Template: ${template.name} (${template.id})`),template.description)console.log(`Description: ${template.description}`);if(template.icon)console.log(`Icon: ${template.icon}`);console.log(`Built-in: ${template.isBuiltin?"yes":"no"}`),printColumnPipeline(template.columns,`Pipeline (${template.columns.length} columns)`)}async function handleTemplateCreate(name,options){let tmpl=await getTemplateService();if(options.fromBoard){let board=await(await getBoardService()).getBoard(options.fromBoard);if(!board)throw Error(`Board not found: ${options.fromBoard}`);let template2=await tmpl.snapshotFromBoard(board.id,name);console.log(`Created template "${template2.name}" (${template2.id}) from board "${board.name}" with ${template2.columns.length} columns`);return}let columns;if(options.columns)columns=options.columns.split(",").map((colName,i2)=>({id:crypto.randomUUID(),name:colName.trim(),label:colName.trim(),gate:"human",action:null,auto_advance:!1,transitions:[],roles:["*"],color:"#94a3b8",parallel:!1,on_fail:null,position:i2}));let template=await tmpl.createTemplate({name,description:options.description,columns});console.log(`Created template "${template.name}" (${template.id}) with ${template.columns.length} columns`)}async function handleTemplateEdit(name,options){let tmpl=await getTemplateService(),template=await tmpl.getTemplate(name);if(!template)throw Error(`Template not found: ${name}`);if(!options.column)console.error("Error: --column is required for template edit."),process.exit(1);let updates={};if(options.gate)updates.gate=options.gate;if(options.action)updates.action=options.action;if(options.color)updates.color=options.color;if(options.rename)updates.name=options.rename,updates.label=options.rename;if(!await tmpl.updateTemplateColumn(template.id,options.column,updates))throw Error(`Failed to update template: ${name}`);console.log(`Updated column "${options.column}" on template "${template.name}".`)}async function handleTemplateRename(oldName,newName){let tmpl=await getTemplateService(),template=await tmpl.getTemplate(oldName);if(!template)throw Error(`Template not found: ${oldName}`);let updated=await tmpl.renameTemplate(template.id,newName);if(!updated)throw Error(`Failed to rename template: ${oldName}`);console.log(`Renamed template "${oldName}" to "${updated.name}".`)}async function handleTemplateDelete(name){let tmpl=await getTemplateService(),template=await tmpl.getTemplate(name);if(!template)throw Error(`Template not found: ${name}`);if(!await tmpl.deleteTemplate(template.id))throw Error(`Failed to delete template: ${name}`);console.log(`Deleted template "${template.name}" (${template.id}).`)}function registerBoardCommands(program2){let board=program2.command("board").description("Board and pipeline management");board.command("create <name>").description("Create a new board").option("--project <project>","Project name").option("--from <template>","Create from template name").option("--columns <columns>","Comma-separated column names").option("--description <text>","Board description").action(async(name,options)=>{try{await handleBoardCreate(name,options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("list").description("List all boards").option("--project <project>","Filter by project").option("--all","Include archived boards").option("--json","Output as JSON").action(async(options)=>{try{await handleBoardList(options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("show <name...>").description("Show board detail").option("--project <project>","Disambiguate by project").option("--json","Output as JSON").action(async(nameParts,options)=>{try{await handleBoardShow(nameParts.join(" "),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("edit <name...>").description("Edit board or column properties").option("--project <project>","Disambiguate by project").option("--column <col>","Column name to edit").option("--gate <gate>","New gate value (human|agent|human+agent)").option("--action <action>","New action skill").option("--color <color>","New color hex").option("--rename <new>","Rename the column").option("--name <new>","Rename the board itself").option("--description <text>","Update description").action(async(nameParts,options)=>{try{await handleBoardEdit(nameParts.join(" "),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("delete <name...>").description("Delete a board").option("--project <project>","Disambiguate by project").option("--force","Skip confirmation").action(async(nameParts,options)=>{try{await handleBoardDelete(nameParts.join(" "),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("columns <name...>").description("Show board column pipeline").option("--project <project>","Disambiguate by project").option("--json","Output as JSON").action(async(nameParts,options)=>{try{await handleBoardColumns(nameParts.join(" "),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("use <name...>").description("Set active board for current repo").option("--project <project>","Disambiguate by project").action(async(nameParts,options)=>{try{await handleBoardUse(nameParts.join(" "),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("export <name...>").description("Export board as JSON").option("--project <project>","Disambiguate by project").option("--output <file>","Write to file instead of stdout").option("--json","Output as JSON (default, accepted for consistency)").action(async(nameParts,options)=>{try{await handleBoardExport(nameParts.join(" "),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("reconcile <name...>").description("Fix orphaned column_ids by matching task stage to board columns").option("--project <project>","Disambiguate by project").option("--json","Output as JSON").action(async(nameParts,options)=>{try{await handleBoardReconcile(nameParts.join(" "),options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("archive <name...>").description("Archive a board and its unfinished tasks").option("--project <project>","Disambiguate by project").action(async(nameParts,options)=>{try{let ts3=await getTaskService3(),board2=await resolveBoard(nameParts.join(" "),options.project);await ts3.archiveBoard(board2.id),console.log(`Archived board "${board2.name}" and its unfinished tasks.`)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),board.command("import").description("Import board from JSON file").requiredOption("--json <file>","JSON file to import").requiredOption("--project <project>","Target project").action(async(options)=>{try{await handleBoardImport(options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}});let template=board.command("template").description("Board template management");template.command("list").description("List all board templates").option("--json","Output as JSON").action(async(options)=>{try{await handleTemplateList(options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),template.command("show <name>").description("Show template detail with pipeline view").option("--json","Output as JSON").action(async(name,options)=>{try{await handleTemplateShow(name,options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),template.command("create <name>").description("Create a board template").option("--from-board <board>","Create from existing board").option("--columns <columns>","Comma-separated column names").option("--description <text>","Template description").action(async(name,options)=>{try{await handleTemplateCreate(name,options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),template.command("edit <name>").description("Edit a template column").option("--column <col>","Column name to edit").option("--gate <gate>","New gate value (human|agent|human+agent)").option("--action <action>","New action skill").option("--rename <new>","Rename the column").option("--color <color>","New color hex").action(async(name,options)=>{try{await handleTemplateEdit(name,options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),template.command("rename <old> <new>").description("Rename a template").action(async(oldName,newName)=>{try{await handleTemplateRename(oldName,newName)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),template.command("delete <name>").description("Delete a template").action(async(name)=>{try{await handleTemplateDelete(name)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}})}import{execSync as execSync9}from"child_process";var BRAIN_PKG="@automagik/genie-brain",BRAIN_REPO="github:automagik-dev/genie-brain";async function installBrain(){console.log(""),console.log(" Installing genie-brain from GitHub (enterprise)..."),console.log(""),console.log(" Source: https://github.com/automagik-dev/genie-brain"),console.log(" Requires: GitHub org membership (automagik-dev)"),console.log("");try{execSync9(`bun add ${BRAIN_REPO}`,{stdio:"inherit"}),console.log(""),console.log(" \u2713 Brain installed from GitHub."),console.log("");try{let brain=await import(BRAIN_PKG);if(brain.runAllMigrations)console.log(" Running brain migrations..."),await brain.runAllMigrations(),console.log(" \u2713 Brain tables created in Postgres.")}catch{console.log(" \u26A0 Auto-migration skipped. Run: genie brain migrate")}return console.log(""),console.log(" Get started:"),console.log(" genie brain init --name my-brain --path ./brain"),console.log(""),!0}catch(err){let msg=err instanceof Error?err.message:String(err);if(msg.includes("Authentication")||msg.includes("permission")||msg.includes("404"))console.error(" \u2717 Access denied. Brain is enterprise-only."),console.log(""),console.log(" You need:"),console.log(" 1. Membership in the automagik-dev GitHub org"),console.log(" 2. SSH key or GH token configured for git"),console.log(""),console.log(" Manual install:"),console.log(` bun add ${BRAIN_REPO}`),console.log("");else console.error(` \u2717 Install failed: ${msg}`),console.log(""),console.log(" Manual install:"),console.log(` bun add ${BRAIN_REPO}`),console.log("");return!1}}function uninstallBrain(){try{execSync9(`bun remove ${BRAIN_PKG}`,{stdio:"inherit"}),console.log(" \u2713 Brain uninstalled.")}catch{console.error(" Uninstall failed. Manual: bun remove @automagik/genie-brain")}}function isModuleNotFound(msg){return msg.includes("Cannot find")||msg.includes("not found")||msg.includes("MODULE_NOT_FOUND")}function printNotInstalledMessage(){console.log(""),console.log(" Brain is an enterprise knowledge graph engine."),console.log(" It is not installed."),console.log(""),console.log(" Quick install:"),console.log(""),console.log(" genie brain install"),console.log(""),console.log(" Requires GitHub org membership (automagik-dev)."),console.log("")}async function executeBrainCommand(args){try{let brain=await import(BRAIN_PKG);if(brain.execute)await brain.execute(args);else console.error("Brain module loaded but execute() not found."),console.error("Update: genie brain install")}catch(err){let msg=err instanceof Error?err.message:String(err);if(isModuleNotFound(msg))printNotInstalledMessage();else console.error(`Brain error: ${msg}`)}}function registerBrainCommands(program2){program2.command("brain").description("Knowledge graph engine (enterprise)").allowUnknownOption().allowExcessArguments().action(async(_options,cmd)=>{let args=cmd.args;if(args[0]==="install"){await installBrain();return}if(args[0]==="uninstall"){uninstallBrain();return}await executeBrainCommand(args)})}var _brief2;async function getBrief2(){if(!_brief2)_brief2=await Promise.resolve().then(() => (init_brief(),exports_brief));return _brief2}async function handleBrief2(options){let team=options.team??process.env.GENIE_TEAM;if(!team)console.error("Error: --team is required (or set GENIE_TEAM)"),process.exit(1);let agent=options.agent??process.env.GENIE_AGENT_NAME,briefService=await getBrief2(),brief=await briefService.generateBrief({team,agent,since:options.since,repoPath:process.cwd()});console.log(briefService.formatBrief(brief))}function registerBriefCommands(program2){program2.command("brief").description("Show startup brief \u2014 aggregated context since last session").option("--team <name>","Team name (default: GENIE_TEAM)").option("--agent <name>","Agent name (default: GENIE_AGENT_NAME)").option("--since <iso>","Start timestamp (default: last executor end)").action(async(options)=>{try{await handleBrief2(options)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}})}import{existsSync as existsSync28,mkdirSync as mkdirSync13,readFileSync as readFileSync15,unlinkSync as unlinkSync7,writeFileSync as writeFileSync12}from"fs";import{homedir as homedir25}from"os";import{join as join37}from"path";function genieHome3(){return process.env.GENIE_HOME??join37(homedir25(),".genie")}function pidFilePath(){return join37(genieHome3(),"scheduler.pid")}function logFilePath(){return join37(genieHome3(),"logs","scheduler.log")}function systemdDir(){return join37(homedir25(),".config","systemd","user")}function systemdUnitPath(){return join37(systemdDir(),"genie-scheduler.service")}function readPid(){let path2=pidFilePath();if(!existsSync28(path2))return null;let raw=readFileSync15(path2,"utf-8").trim(),pid=Number.parseInt(raw,10);if(Number.isNaN(pid)||pid<=0)return null;return pid}function writePid(pid){let dir=genieHome3();mkdirSync13(dir,{recursive:!0}),writeFileSync12(pidFilePath(),String(pid),"utf-8")}function removePid(){let path2=pidFilePath();if(existsSync28(path2))try{unlinkSync7(path2)}catch{}}function isProcessAlive2(pid){try{return process.kill(pid,0),!0}catch{return!1}}function generateSystemdUnit(){let genieBin=process.argv[1]??"genie";return`[Unit]
2296
2296
  Description=Genie Scheduler Daemon
2297
2297
  Documentation=https://github.com/automagik/genie
2298
2298
  After=network.target
@@ -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.260402.4",
5
+ "version": "4.260402.6",
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.260402.4",
3
+ "version": "4.260402.6",
4
4
  "description": "Collaborative terminal toolkit for human + AI workflows",
5
5
  "type": "module",
6
6
  "bin": {
@@ -9,7 +9,7 @@
9
9
  "scripts": {
10
10
  "prepare": "test \"$CI\" = true || husky",
11
11
  "version": "bun run scripts/version.ts",
12
- "build": "bun build src/genie.ts --outdir dist --target bun --minify-syntax --minify-whitespace --external bun --external pgserve && chmod +x dist/*.js",
12
+ "build": "bun build src/genie.ts --outdir dist --target bun --minify-syntax --minify-whitespace --external bun --external pgserve --external @automagik/genie-brain && chmod +x dist/*.js",
13
13
  "build:app": "bun run scripts/build-app.ts",
14
14
  "build:plugin": "node scripts/build.js",
15
15
  "sync": "node scripts/sync.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genie",
3
- "version": "4.260402.4",
3
+ "version": "4.260402.6",
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.260402.4",
3
+ "version": "4.260402.6",
4
4
  "private": true,
5
5
  "description": "Runtime dependencies for genie bundled CLIs",
6
6
  "type": "module",
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * genie brain — delegate to @automagik/genie-brain (enterprise).
3
3
  *
4
- * This is the integration point. genie CLI dynamically imports brain
5
- * and passes all args through. If brain isn't installed, prints
6
- * install instructions and offers `genie brain install`.
4
+ * Brain installs directly from the private GitHub repo.
5
+ * Only people with repo access can install = enterprise license.
6
+ * Source code stays in git, never published to npm.
7
7
  *
8
8
  * Brain is NEVER a hard dependency. genie works exactly the same
9
9
  * without it. Zero behavior change for OSS users.
@@ -13,48 +13,26 @@ import { execSync } from 'node:child_process';
13
13
  import type { Command } from 'commander';
14
14
 
15
15
  const BRAIN_PKG = '@automagik/genie-brain';
16
- const BRAIN_REGISTRY = 'https://npm.pkg.github.com';
17
- const BRAIN_SCOPE = '@automagik';
16
+ const BRAIN_REPO = 'github:automagik-dev/genie-brain';
18
17
 
19
- /** Install brain package from GitHub Packages */
18
+ /** Install brain package directly from GitHub repo */
20
19
  async function installBrain(): Promise<boolean> {
21
20
  console.log('');
22
- console.log(' Installing @automagik/genie-brain (enterprise)...');
21
+ console.log(' Installing genie-brain from GitHub (enterprise)...');
22
+ console.log('');
23
+ console.log(' Source: https://github.com/automagik-dev/genie-brain');
24
+ console.log(' Requires: GitHub org membership (automagik-dev)');
23
25
  console.log('');
24
26
 
25
27
  try {
26
- // Configure npm scope for GitHub Packages (idempotent)
27
- execSync(`npm config set ${BRAIN_SCOPE}:registry ${BRAIN_REGISTRY}`, { stdio: 'inherit' });
28
-
29
- // Check if user has a GitHub token configured
30
- let hasToken = false;
31
- try {
32
- const rc = execSync(`npm config get //${BRAIN_REGISTRY.replace('https://', '')}/:_authToken`, {
33
- encoding: 'utf-8',
34
- stdio: ['pipe', 'pipe', 'pipe'],
35
- }).trim();
36
- hasToken = rc.length > 0 && rc !== 'undefined';
37
- } catch {
38
- /* no token */
39
- }
40
-
41
- if (!hasToken) {
42
- console.log(' GitHub Packages requires authentication.');
43
- console.log(' Set your token:');
44
- console.log('');
45
- console.log(` echo "//npm.pkg.github.com/:_authToken=YOUR_GITHUB_TOKEN" >> ~/.npmrc`);
46
- console.log('');
47
- console.log(' Generate a token at: https://github.com/settings/tokens');
48
- console.log(' Required scope: read:packages');
49
- console.log('');
50
- return false;
51
- }
52
-
53
- // Install the package
54
- execSync(`bun add ${BRAIN_PKG}`, { stdio: 'inherit' });
28
+ // Install directly from GitHub bun resolves git repos natively
29
+ // Only people with repo access (SSH key or GH token) can install
30
+ execSync(`bun add ${BRAIN_REPO}`, {
31
+ stdio: 'inherit',
32
+ });
55
33
 
56
34
  console.log('');
57
- console.log(' ✓ Brain installed successfully.');
35
+ console.log(' ✓ Brain installed from GitHub.');
58
36
  console.log('');
59
37
 
60
38
  // Auto-run migrations
@@ -76,12 +54,24 @@ async function installBrain(): Promise<boolean> {
76
54
  return true;
77
55
  } catch (err: unknown) {
78
56
  const msg = err instanceof Error ? err.message : String(err);
79
- console.error(` ✗ Install failed: ${msg}`);
80
- console.log('');
81
- console.log(' Manual install:');
82
- console.log(` npm config set ${BRAIN_SCOPE}:registry ${BRAIN_REGISTRY}`);
83
- console.log(` bun add ${BRAIN_PKG}`);
84
- console.log('');
57
+
58
+ if (msg.includes('Authentication') || msg.includes('permission') || msg.includes('404')) {
59
+ console.error(' Access denied. Brain is enterprise-only.');
60
+ console.log('');
61
+ console.log(' You need:');
62
+ console.log(' 1. Membership in the automagik-dev GitHub org');
63
+ console.log(' 2. SSH key or GH token configured for git');
64
+ console.log('');
65
+ console.log(' Manual install:');
66
+ console.log(` bun add ${BRAIN_REPO}`);
67
+ console.log('');
68
+ } else {
69
+ console.error(` ✗ Install failed: ${msg}`);
70
+ console.log('');
71
+ console.log(' Manual install:');
72
+ console.log(` bun add ${BRAIN_REPO}`);
73
+ console.log('');
74
+ }
85
75
  return false;
86
76
  }
87
77
  }
@@ -119,7 +109,7 @@ async function executeBrainCommand(args: string[]): Promise<void> {
119
109
  await brain.execute(args);
120
110
  } else {
121
111
  console.error('Brain module loaded but execute() not found.');
122
- console.error('Update: bun add @automagik/genie-brain@latest');
112
+ console.error('Update: genie brain install');
123
113
  }
124
114
  } catch (err: unknown) {
125
115
  const msg = err instanceof Error ? err.message : String(err);