@automagik/genie 4.260501.6 → 4.260502.1

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
@@ -833,7 +833,26 @@ ${errCtx.stack}`;d.reject(err)}else d.resolve(msg)}});return sub.requestSubject=
833
833
  FROM executors e
834
834
  JOIN agents a ON e.agent_id = a.id
835
835
  WHERE e.claude_session_id IS NOT NULL
836
- `;for(let row of rows)map2.set(row.claude_session_id,{agentId:row.agent_id,executorId:row.executor_id,team:row.team,wishSlug:row.wish_slug,taskId:row.task_id,role:row.role})}catch{}return workerMapCache={map:map2,expires:Date.now()+WORKER_MAP_TTL_MS},map2}function workerToContext(worker){return{agentId:worker?.agentId??null,team:worker?.team??null,wishSlug:worker?.wishSlug??null,taskId:worker?.taskId??null,lastOffset:0,totalTurns:0}}async function resolveSafeParentId(sql,parentSessionId){if(!parentSessionId)return null;return(await sql`SELECT 1 FROM sessions WHERE id = ${parentSessionId} LIMIT 1`).length>0?parentSessionId:null}async function ensureSession(sql,sessionId,jsonlPath,projectPath,workerMap,opts){let existing=await sql`SELECT agent_id, team, wish_slug, task_id, last_ingested_offset, total_turns FROM sessions WHERE id = ${sessionId}`;if(existing.length>0){let row=existing[0];return{agentId:row.agent_id,team:row.team,wishSlug:row.wish_slug,taskId:row.task_id,lastOffset:row.last_ingested_offset??0,totalTurns:row.total_turns??0}}let worker=workerMap.get(sessionId),parentSessionId=await resolveSafeParentId(sql,opts?.parentSessionId);return await sql`
836
+ `;for(let row of rows)map2.set(row.claude_session_id,{agentId:row.agent_id,executorId:row.executor_id,team:row.team,wishSlug:row.wish_slug,taskId:row.task_id,role:row.role})}catch{}return workerMapCache={map:map2,expires:Date.now()+WORKER_MAP_TTL_MS},map2}function workerToContext(worker){return{agentId:worker?.agentId??null,team:worker?.team??null,wishSlug:worker?.wishSlug??null,taskId:worker?.taskId??null,lastOffset:0,totalTurns:0}}async function resolveSafeParentId(sql,parentSessionId){if(!parentSessionId)return null;return(await sql`SELECT 1 FROM sessions WHERE id = ${parentSessionId} LIMIT 1`).length>0?parentSessionId:null}async function ensureSession(sql,sessionId,jsonlPath,projectPath,workerMap,opts){let worker=workerMap.get(sessionId),existing=await sql`
837
+ SELECT executor_id, agent_id, team, wish_slug, task_id, role, status, last_ingested_offset, total_turns
838
+ FROM sessions WHERE id = ${sessionId}
839
+ `;if(existing.length>0){let row=existing[0];if(worker!==void 0&&(row.executor_id===null||row.agent_id===null||row.team===null||row.wish_slug===null||row.task_id===null||row.role===null||row.status==="orphaned")){let[upgraded]=await sql`
840
+ UPDATE sessions SET
841
+ executor_id = COALESCE(executor_id, ${worker.executorId??null}),
842
+ agent_id = COALESCE(agent_id, ${worker.agentId??null}),
843
+ team = COALESCE(team, ${worker.team??null}),
844
+ wish_slug = COALESCE(wish_slug, ${worker.wishSlug??null}),
845
+ task_id = COALESCE(task_id, ${worker.taskId??null}),
846
+ role = COALESCE(role, ${worker.role??null}),
847
+ status = CASE
848
+ WHEN status = 'orphaned' AND ${worker.agentId??null}::text IS NOT NULL
849
+ THEN 'active'
850
+ ELSE status
851
+ END,
852
+ updated_at = now()
853
+ WHERE id = ${sessionId}
854
+ RETURNING agent_id, team, wish_slug, task_id, last_ingested_offset, total_turns
855
+ `;return{agentId:upgraded.agent_id,team:upgraded.team,wishSlug:upgraded.wish_slug,taskId:upgraded.task_id,lastOffset:upgraded.last_ingested_offset??0,totalTurns:upgraded.total_turns??0}}return{agentId:row.agent_id,team:row.team,wishSlug:row.wish_slug,taskId:row.task_id,lastOffset:row.last_ingested_offset??0,totalTurns:row.total_turns??0}}let parentSessionId=await resolveSafeParentId(sql,opts?.parentSessionId);return await sql`
837
856
  INSERT INTO sessions (id, agent_id, executor_id, team, wish_slug, task_id, role, project_path, jsonl_path, status, last_ingested_offset, total_turns, parent_session_id, is_subagent, file_size, file_mtime)
838
857
  VALUES (${sessionId}, ${worker?.agentId??null}, ${worker?.executorId??null}, ${worker?.team??null}, ${worker?.wishSlug??null}, ${worker?.taskId??null}, ${worker?.role??null}, ${projectPath}, ${jsonlPath}, ${worker?"active":"orphaned"}, 0, 0, ${parentSessionId}, ${opts?.isSubagent??!1}, ${opts?.fileSize??0}, ${opts?.mtime??0})
839
858
  ON CONFLICT (id) DO NOTHING
@@ -904,10 +923,10 @@ ${errCtx.stack}`;d.reject(err)}else d.resolve(msg)}});return sub.requestSubject=
904
923
  ${sql.array(rows.map((r)=>r.is_error))}::bool[],
905
924
  ${sql.array(rows.map((r)=>r.error_message??""))}::text[],
906
925
  ${sql.array(rows.map((r)=>r.duration_ms??0))}::int[],
907
- ${sql.array(rows.map((r)=>r.agent_id??""))}::text[],
908
- ${sql.array(rows.map((r)=>r.team??""))}::text[],
909
- ${sql.array(rows.map((r)=>r.wish_slug??""))}::text[],
910
- ${sql.array(rows.map((r)=>r.task_id??""))}::text[]
926
+ ${sql.array(rows.map((r)=>r.agent_id??null))}::text[],
927
+ ${sql.array(rows.map((r)=>r.team??null))}::text[],
928
+ ${sql.array(rows.map((r)=>r.wish_slug??null))}::text[],
929
+ ${sql.array(rows.map((r)=>r.task_id??null))}::text[]
911
930
  )
912
931
  ON CONFLICT (session_id, tool_use_id) DO NOTHING
913
932
  `}async function ingestFile(sql,sessionId,jsonlPath,projectPath,fromOffset,opts){let chunkSize=opts?.chunkSize??DEFAULT_CHUNK_SIZE,workerMap=opts?.workerMap??await buildWorkerMap(sql),session=await ensureSession(sql,sessionId,jsonlPath,projectPath,workerMap,{parentSessionId:opts?.parentSessionId,isSubagent:opts?.isSubagent,fileSize:opts?.fileSize,mtime:opts?.mtime}),fileSize;try{fileSize=(await stat3(jsonlPath)).size}catch{return{newOffset:fromOffset,contentRowsInserted:0,toolEventsInserted:0}}let effectiveOffset=Math.max(fromOffset,session.lastOffset);if(fileSize<=effectiveOffset)return{newOffset:effectiveOffset,contentRowsInserted:0,toolEventsInserted:0};let bytesAvailable=fileSize-effectiveOffset,bytesToRead=Math.min(bytesAvailable,chunkSize),fh=await open3(jsonlPath,"r");try{let buf=Buffer.alloc(bytesToRead),{bytesRead}=await fh.read(buf,0,bytesToRead,effectiveOffset);if(bytesRead===0)return{newOffset:effectiveOffset,contentRowsInserted:0,toolEventsInserted:0};let raw=buf.subarray(0,bytesRead).toString("utf-8"),safeEnd=raw.length;if(bytesRead===chunkSize&&bytesAvailable>chunkSize){let lastNewline=raw.lastIndexOf(`
@@ -1763,7 +1782,18 @@ ${gitLog}`:"","",gitStatus?`Uncommitted changes:
1763
1782
  ${gitStatus}`:"","","Pick up where you left off. Read the wish file for full context."].filter(Boolean).join(`
1764
1783
  `);await _deps3.mailboxSend(repoPath,"genie",workerId,resumePrompt)}catch(err){let msg=err instanceof Error?err.message:String(err);console.warn(`[protocol-router] Resume context injection failed: ${msg}`)}}var execAsync,_deps3;var init_protocol_router_spawn=__esm(()=>{init_agent_registry();init_audit();init_claude_native_teams();init_db();init_executor_registry();init_mailbox();init_provider_adapters();init_registry2();init_should_resume();init_team_manager();init_tmux_wrapper();init_tmux();init_wish_state();execAsync=promisify2(exec2),_deps3={findAnyGroupByAssignee,mailboxSend:send,writeNativeInbox}});async function waitForAgentReady(paneId,opts){let timeoutMs=opts?.timeoutMs??(process.env.GENIE_SPAWN_TIMEOUT_MS?Number(process.env.GENIE_SPAWN_TIMEOUT_MS):DEFAULT_SPAWN_TIMEOUT_MS),pollIntervalMs=opts?.pollIntervalMs??READINESS_POLL_INTERVAL_MS,start=Date.now();while(Date.now()-start<timeoutMs){try{let content=await capturePaneContent(paneId,50);if(content){let state=detectState(content);if(state.type==="idle"||state.type==="tool_use")return{ready:!0,elapsedMs:Date.now()-start}}}catch{}await new Promise((r)=>setTimeout(r,pollIntervalMs))}return{ready:!1,elapsedMs:Date.now()-start}}async function waitForExecutorReady(executorId,opts){let timeoutMs=opts?.timeoutMs??DEFAULT_SPAWN_TIMEOUT_MS,start=Date.now();if(!await _pgDeps.isAvailable())return{ready:!1,elapsedMs:0};try{let executor=await _pgDeps.getExecutor(executorId);if(executor&&(executor.state==="running"||executor.state==="idle"))return{ready:!0,elapsedMs:Date.now()-start}}catch{return{ready:!1,elapsedMs:Date.now()-start}}let sql;try{sql=await _pgDeps.getConnection()}catch{return{ready:!1,elapsedMs:Date.now()-start}}return new Promise((resolve7)=>{let resolved=!1,listener=null,pollInterval=null,timeout=null,cleanup=async()=>{if(pollInterval)clearInterval(pollInterval);if(timeout)clearTimeout(timeout);if(listener)try{await listener.unlisten()}catch{}},finish=(ready)=>{if(resolved)return;resolved=!0,cleanup().then(()=>resolve7({ready,elapsedMs:Date.now()-start}))};timeout=setTimeout(()=>finish(!1),timeoutMs),sql.listen("genie_executor_state",(payload)=>{let parts=payload.split(":");if(parts.length<4)return;let[notifyExecId,,,newState]=parts;if(notifyExecId===executorId&&(newState==="running"||newState==="idle"))finish(!0)}).then((l)=>{if(listener=l,resolved)l.unlisten().catch(()=>{})}).catch(()=>{}),pollInterval=setInterval(async()=>{if(resolved)return;try{let executor=await _pgDeps.getExecutor(executorId);if(executor&&(executor.state==="running"||executor.state==="idle"))finish(!0)}catch{}},READINESS_POLL_INTERVAL_MS)})}var DEFAULT_SPAWN_TIMEOUT_MS=30000,READINESS_POLL_INTERVAL_MS=2000,_pgDeps;var init_spawn_command=__esm(()=>{init_db();init_executor_registry();init_orchestrator();init_tmux();_pgDeps={isAvailable,getConnection,getExecutor}});var exports_protocol_router={};__export(exports_protocol_router,{sendMessage:()=>sendMessage2,resolveResumeSessionId:()=>resolveResumeSessionId,getInbox:()=>getInbox,deliverToPane:()=>deliverToPane,_deps:()=>_deps4,MissingResumeSessionError:()=>MissingResumeSessionError});async function waitForWorkerReady(paneId,timeoutMs=AUTO_SPAWN_READY_TIMEOUT_MS){try{let executor=await findExecutorByPane(paneId);if(executor&&executor.state!=="terminated"&&executor.state!=="error"){if((await waitForExecutorReady(executor.id,{timeoutMs})).ready)return!0}}catch{}let start=Date.now();while(Date.now()-start<timeoutMs){try{let content=await capturePaneContent(paneId,30);if(detectState(content).type==="idle")return!0}catch{}await new Promise((r)=>setTimeout(r,AUTO_SPAWN_POLL_INTERVAL_MS))}return!1}async function isExecutorCompleted(worker){if(!worker?.currentExecutorId)return!1;let executor=await getCurrentExecutor(worker.id);return executor!=null&&(executor.state==="done"||executor.state==="terminated")}async function isExecutorResumable(worker){if(!worker.currentExecutorId)return!1;let executor=await getCurrentExecutor(worker.id);if(!executor)return!1;return!["done","error","terminated"].includes(executor.state)}async function isWorkerDead(w){if(w.currentExecutorId){let state=await getAgentEffectiveState(w.id);return state==="terminated"||state==="offline"}return w.state==="suspended"}async function resolveRecipient(recipientId){let allWorkers=await list(),byId=[],byRole=[],byTeamRole=[];for(let w of allWorkers){if(await isWorkerDead(w))continue;if(!await _deps4.isPaneAlive(w.paneId))continue;if(w.id===recipientId)byId.push(w);else if(w.role===recipientId)byRole.push(w);else if(`${w.team}:${w.role}`===recipientId)byTeamRole.push(w)}if(byId.length>0)return byId;if(byRole.length>0)return byRole;return byTeamRole}function dedupShadowsForSend(workers){let groups=new Map;for(let w of workers){let key=`${w.customName??w.id}\x00${w.team??""}`,arr=groups.get(key);if(arr)arr.push(w);else groups.set(key,[w])}let out=[];for(let arr of groups.values()){if(arr.length===1){out.push(arr[0]);continue}arr.sort((a,b2)=>{let aExec=a.currentExecutorId!=null?1:0,bExec=b2.currentExecutorId!=null?1:0;if(aExec!==bExec)return bExec-aExec;return(b2.startedAt??"").localeCompare(a.startedAt??"")}),out.push(arr[0])}return out}async function findLiveWorkerFuzzy(recipientId){let matches=dedupShadowsForSend(await resolveRecipient(recipientId));return matches.length===1?matches[0]:null}async function findSpawnTemplate(worker,recipientId){let templates=await listTemplates(),candidates=[worker?.role,worker?.id,recipientId].filter((v)=>Boolean(v)),uniqueCandidates=[...new Set(candidates)],workerTeam=worker?.team;return templates.find((t)=>{if(workerTeam&&t.team!==workerTeam)return!1;return uniqueCandidates.some((q)=>t.id===q||t.role===q||`${t.team}:${t.role}`===q)})??null}async function lockedSpawnWorker(recipientId,worker,template,resumeSessionId){let sql=await getConnection(),workerTeam=worker?.team,lockResult=await sql.begin(async(tx)=>{await tx`SELECT pg_advisory_xact_lock(hashtext(${recipientId}))`;let postLockLive=await findLiveWorkerFuzzy(recipientId);if(postLockLive)return{type:"existing",worker:postLockLive};if(await cleanupDeadWorkers(recipientId,workerTeam),worker)await unregister(worker.id);let{spawnWorkerFromTemplate:spawnWorkerFromTemplate2}=await Promise.resolve().then(() => (init_protocol_router_spawn(),exports_protocol_router_spawn));return{type:"spawned",...await spawnWorkerFromTemplate2(template,resumeSessionId)}});if(lockResult.type==="existing")return{worker:lockResult.worker,respawned:!1};if(await saveTemplate({...template,lastSpawnedAt:new Date().toISOString()}),await(_deps4.waitForWorkerReady??waitForWorkerReady)(lockResult.paneId),!await _deps4.isPaneAlive(lockResult.paneId))return await unregister(lockResult.worker.id),null;return{worker:lockResult.worker,respawned:!0}}async function resolveResumeSessionId(worker,template,recipientId){if(template.provider!=="claude")return;let agentIdToProbe=worker?.id??`dir:${recipientId}`,decision=await shouldResume(agentIdToProbe);if(worker&&await isExecutorResumable(worker)){if(!decision.sessionId)throw new MissingResumeSessionError(worker.id,recipientId)}return decision.sessionId}async function handleSpawnError(err,worker,recipientId){if(err instanceof MissingResumeSessionError)throw err;let msg=err instanceof Error?err.message:String(err);if(console.error(`[protocol-router] Spawn failed for "${recipientId}": ${msg}`),worker)await update(worker.id,{state:"error"}).catch(()=>{});return null}async function ensureWorkerAlive(worker,recipientId){if(worker&&worker.state!=="suspended"&&await _deps4.isPaneAlive(worker.paneId))return{worker,respawned:!1};let live=await findLiveWorkerFuzzy(recipientId);if(live)return{worker:live,respawned:!1};if(await isExecutorCompleted(worker))return null;if(!process.env.TMUX)return null;let template=await findSpawnTemplate(worker,recipientId);if(!template)return null;let resumeSessionId=await resolveResumeSessionId(worker,template,recipientId);try{return await lockedSpawnWorker(recipientId,worker,template,resumeSessionId)}catch(err){return handleSpawnError(err,worker,recipientId)}}async function cleanupDeadWorkers(recipientId,team){let allWorkers=await list();for(let w of allWorkers){if(team&&w.team!==team)continue;if(!(w.role===recipientId||w.id===recipientId))continue;if(await _deps4.isPaneAlive(w.paneId))continue;await unregister(w.id)}}async function deliverToWorker(repoPath,from,worker,body){let message=await send(repoPath,from,worker.id,body),delivered=!1;if(worker.nativeTeamEnabled&&worker.team&&worker.role)delivered=await writeToNativeInbox(worker,message);else delivered=await injectToTmuxPane(worker,message);if(!delivered&&worker.team){let agentName=worker.role||worker.id.split("-").slice(-1)[0]||worker.id;try{let nativeMsg=toNativeInboxMessage(message,worker.nativeColor??"blue");await writeNativeInbox(worker.team,agentName,nativeMsg),delivered=!0}catch{}}if(delivered)await markDelivered(repoPath,worker.id,message.id);else console.error(`[protocol-router] Delivery failed: all paths exhausted (worker=${worker.id}, pane=${worker.paneId}, msg="${body.slice(0,50)}")`);return{messageId:message.id,workerId:worker.id,delivered}}async function deliverViaNativeInbox(repoPath,from,to,body,teamName){let resolvedTeam=teamName??await discoverTeamName();if(!resolvedTeam)return null;let config=await loadConfig(resolvedTeam).catch(()=>null);if(!config)return null;let sanitizedTo=sanitizeTeamName(to),matchedMember=config.members?.find((m)=>m.name===to||m.name===sanitizedTo||m.agentId===`${to}@${resolvedTeam}`||m.agentId===`${sanitizedTo}@${resolvedTeam}`);if(!matchedMember)return null;let inboxName=matchedMember.name??to;try{let message=await send(repoPath,from,to,body),nativeMsg={from,text:body,summary:body.length>50?`${body.substring(0,50)}...`:body,timestamp:new Date().toISOString(),color:"blue",read:!1};return await writeNativeInbox(resolvedTeam,inboxName,nativeMsg),await markDelivered(repoPath,to,message.id),{messageId:message.id,workerId:to,delivered:!0}}catch{return null}}async function deliverAfterPaneRecheck(repoPath,from,worker,body,paneDeadReason){if(!await _deps4.isPaneAlive(worker.paneId)){let message=await send(repoPath,from,worker.id,body);return console.error(`[protocol-router] Delivery failed: ${paneDeadReason} (worker=${worker.id}, msg="${body.slice(0,50)}")`),{messageId:message.id,workerId:worker.id,delivered:!1,reason:paneDeadReason}}return deliverToWorker(repoPath,from,worker,body)}async function findKnownWorker(to){let worker=await get(to);if(worker)return worker;let allWorkers=await list();return allWorkers.find((w)=>w.role===to&&w.state==="suspended")??allWorkers.find((w)=>w.role===to)??null}async function attemptAutoSpawnDelivery(repoPath,from,to,body,worker){let alive;try{alive=await ensureWorkerAlive(worker,to)}catch(err){if(err instanceof MissingResumeSessionError)return console.error(`[protocol-router] ${err.message}`),{messageId:"",workerId:worker?.id??to,delivered:!1,reason:err.message};throw err}if(!alive)return null;return deliverAfterPaneRecheck(repoPath,from,alive.worker,body,"pane dead after spawn")}async function sendMessage2(repoPath,from,to,body,teamName){if(from===to)return{messageId:"",workerId:to,delivered:!0,reason:"Self-delivery suppressed"};let liveMatches=await resolveRecipient(to);if(liveMatches.length===1)return deliverAfterPaneRecheck(repoPath,from,liveMatches[0],body,"Pane died before delivery");if(liveMatches.length>1)return{messageId:"",workerId:to,delivered:!1,reason:`Worker "${to}" is ambiguous. Found ${liveMatches.length} live matches: ${liveMatches.map((m)=>m.id).join(", ")}. Use exact worker ID.`};let{resolve:resolve7}=await Promise.resolve().then(() => (init_agent_directory(),exports_agent_directory)),dirResolved=await resolve7(to),worker=await findKnownWorker(to);if(dirResolved||worker){let result2=await attemptAutoSpawnDelivery(repoPath,from,to,body,worker);if(result2)return result2}let nativeResult=await deliverViaNativeInbox(repoPath,from,to,body,teamName);if(nativeResult)return nativeResult;return{messageId:"",workerId:to,delivered:!1,reason:`Worker "${to}" not found or not alive`}}async function writeToNativeInbox(worker,message){try{let nativeMsg=toNativeInboxMessage(message,worker.nativeColor??"blue"),agentName=worker.role??worker.id;return await writeNativeInbox(worker.team??"",agentName,nativeMsg),!0}catch{return!1}}async function injectToTmuxPane(worker,message){if(!worker.paneId)return!1;if(!/^%\d+$/.test(worker.paneId))return!1;if(!await _deps4.isPaneAlive(worker.paneId))return!1;try{let escaped=message.body.replace(/'/g,"'\\''");return await executeTmux2(`send-keys -t '${worker.paneId}' '${escaped}'`),await new Promise((resolve7)=>setTimeout(resolve7,200)),await executeTmux2(`send-keys -t '${worker.paneId}' Enter`),!0}catch{return!1}}async function deliverToPane(toWorker,messageId){let worker=await get(toWorker);if(!worker||!worker.paneId)return await markFailed(messageId),!1;if(!await _deps4.isPaneAlive(worker.paneId))return await markFailed(messageId),!1;let message=await getById(messageId);if(!message||message.deliveredAt)return!1;let injected=await injectToTmuxPane(worker,message);if(injected&&worker.repoPath)await markDelivered(worker.repoPath,worker.id,messageId);else await markFailed(messageId);return injected}async function getInbox(repoPath,workerId){return inbox(repoPath,workerId)}var MissingResumeSessionError,_deps4,AUTO_SPAWN_READY_TIMEOUT_MS=15000,AUTO_SPAWN_POLL_INTERVAL_MS=1000;var init_protocol_router=__esm(()=>{init_agent_registry();init_claude_native_teams();init_db();init_executor_registry();init_mailbox();init_orchestrator();init_should_resume();init_spawn_command();init_tmux();MissingResumeSessionError=class MissingResumeSessionError extends Error{workerId;entityId;recipientId;reason;constructor(workerId,recipientId,reason="null_session"){let suffix=recipientId?` (recipient "${recipientId}")`:"";super(`Cannot resume worker "${workerId}"${suffix}: executor has no claude_session_id recorded (reason: ${reason}). This usually means the worker predates the session-sync hook. Run \`genie reset ${workerId}\` or re-spawn the worker to recover.`);this.name="MissingResumeSessionError",this.workerId=workerId,this.entityId=workerId,this.recipientId=recipientId,this.reason=reason}};_deps4={isPaneAlive,waitForWorkerReady:null}});var exports_sdk_session_capture={};__export(exports_sdk_session_capture,{updateTurnCount:()=>updateTurnCount,startSession:()=>startSession,recordTurn:()=>recordTurn,endSession:()=>endSession});async function startSession(safePgCall,executorId,claudeSessionId,agentId,team,role,wishSlug){let sessionId=claudeSessionId??`sdk-${executorId}-${Date.now()}`;if(!await safePgCall("sdk-session-start",(sql)=>sql`INSERT INTO sessions (id, agent_id, executor_id, team, role, wish_slug, status, jsonl_path, project_path)
1765
1784
  VALUES (${sessionId}, ${agentId}, ${executorId}, ${team??null}, ${role??null}, ${wishSlug??null}, 'active', '', '')
1766
- ON CONFLICT (id) DO NOTHING
1785
+ ON CONFLICT (id) DO UPDATE SET
1786
+ agent_id = COALESCE(sessions.agent_id, EXCLUDED.agent_id),
1787
+ executor_id = COALESCE(sessions.executor_id, EXCLUDED.executor_id),
1788
+ team = COALESCE(sessions.team, EXCLUDED.team),
1789
+ role = COALESCE(sessions.role, EXCLUDED.role),
1790
+ wish_slug = COALESCE(sessions.wish_slug, EXCLUDED.wish_slug),
1791
+ status = CASE
1792
+ WHEN sessions.status = 'orphaned' AND EXCLUDED.agent_id IS NOT NULL
1793
+ THEN 'active'
1794
+ ELSE sessions.status
1795
+ END,
1796
+ updated_at = now()
1767
1797
  RETURNING id`,null,{executorId,chatId:""}))return null;return sessionId}async function recordTurn(safePgCall,sessionId,turnIndex,role,content,toolName,timestamp2){let ts3=timestamp2??new Date().toISOString();await safePgCall("sdk-session-turn",(sql)=>sql`INSERT INTO session_content (session_id, turn_index, role, content, tool_name, timestamp)
1768
1798
  VALUES (${sessionId}, ${turnIndex}, ${role}, ${content}, ${toolName??null}, ${ts3})
1769
1799
  ON CONFLICT (session_id, turn_index) DO NOTHING`,void 0,{executorId:"",chatId:""})}async function updateTurnCount(safePgCall,sessionId,totalTurns){await safePgCall("sdk-session-turn-count",(sql)=>sql`UPDATE sessions SET total_turns = ${totalTurns}, updated_at = now() WHERE id = ${sessionId}`,void 0,{executorId:"",chatId:""})}async function endSession(safePgCall,sessionId,status="completed"){await safePgCall("sdk-session-end",(sql)=>sql`UPDATE sessions SET ended_at = now(), status = ${status}, updated_at = now() WHERE id = ${sessionId}`,void 0,{executorId:"",chatId:""})}var exports_claude_sdk_stream={};__export(exports_claude_sdk_stream,{formatSdkMessage:()=>formatSdkMessage});function formatSdkMessage(msg,format){switch(format){case"text":return formatText(msg);case"json":return JSON.stringify(msg,null,2);case"ndjson":return JSON.stringify(msg)}}function formatText(msg){switch(msg.type){case"assistant":return formatAssistant(msg);case"stream_event":return formatStreamEvent(msg);case"result":return formatResult(msg);case"tool_progress":return`[${msg.tool_name}] progress... (${msg.elapsed_time_seconds}s)
@@ -2132,7 +2162,7 @@ ${bodyHash}`}function signOmniRequest(method,path3,body){let paths=keyPaths(),ho
2132
2162
  [omni-signature] Run \`genie omni handshake\` to register this host and enable signed requests.
2133
2163
  `)}return null}let timestamp2=new Date().toISOString(),canonical=canonicalSigningInput(timestamp2,method,path3,body),signature=sign(null,Buffer.from(canonical,"utf-8"),key).toString("base64url");return{"X-Genie-Host-Id":host.hostId,"X-Genie-Timestamp":timestamp2,"X-Genie-Signature":signature}}var warnedMissingKey=!1,cachedKey=null,cachedKeyPath=null;var init_omni_signature=()=>{};var exports_frontmatter_writer={};__export(exports_frontmatter_writer,{writeFrontmatter:()=>writeFrontmatter,serializeSdkConfig:()=>serializeSdkConfig});import{readFileSync as readFileSync27,writeFileSync as writeFileSync16}from"fs";function writeFrontmatter(filePath,updates){let content=readFileSync27(filePath,"utf-8"),{yamlObj,body}=splitFrontmatter(content),merged={...yamlObj,...stripUndefined(updates)},output=`---
2134
2164
  ${dump(merged,{lineWidth:-1,noRefs:!0,sortKeys:!1,quotingType:'"'})}---
2135
- ${body}`;writeFileSync16(filePath,output,"utf-8")}function serializeSdkConfig(sdk){let result2={};for(let[key,value]of Object.entries(sdk)){if(value===void 0||value===null)continue;if(Array.isArray(value)&&value.length===0)continue;if(typeof value==="object"&&!Array.isArray(value)&&Object.keys(value).length===0)continue;result2[key]=value}return result2}function splitFrontmatter(content){let match=content.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);if(!match)return{yamlObj:{},body:content};let yamlStr=match[1],body=match[2],yamlObj={};try{let parsed=load(yamlStr);if(typeof parsed==="object"&&parsed!==null)yamlObj=parsed}catch{}return{yamlObj,body}}function stripUndefined(obj){let result2={};for(let[key,value]of Object.entries(obj))if(value!==void 0)result2[key]=value;return result2}var init_frontmatter_writer=__esm(()=>{init_js_yaml()});import{existsSync as existsSync43,realpathSync as realpathSync5}from"fs";import{homedir as homedir34}from"os";import{join as join52,resolve as resolve7}from"path";function getCwd(deps){return deps.cwd??process.cwd()}function getHomeDir(deps){return deps.homeDir??homedir34()}function getWorkspaceRoot(deps){if("workspaceRoot"in deps)return deps.workspaceRoot??null;return findWorkspace()?.root??null}function getConfig(deps){return deps.config??loadGenieConfigSync()}function expandHome(path3,homeDir){if(path3==="~")return homeDir;if(path3.startsWith("~/"))return join52(homeDir,path3.slice(2));return path3}function normalizeBrainVaultPath(path3,deps){return resolve7(getCwd(deps),expandHome(path3,getHomeDir(deps)))}function canonicalBrainVaultPath(path3,deps){let realpath=deps.realpath??realpathSync5;try{return realpath(path3)}catch{return resolve7(path3)}}function dedupeBrainVaultPaths(paths,deps={}){let seen=new Set,deduped=[];for(let path3 of paths){let canonical=canonicalBrainVaultPath(path3,deps);if(seen.has(canonical))continue;seen.add(canonical),deduped.push(canonical)}return deduped}function hasBrainJson(path3,deps){return(deps.exists??existsSync43)(join52(path3,"brain.json"))}function filterVaultsWithBrainJson(paths,source,deps){let warn=deps.warn??console.warn,label=source==="config"?"configured":source==="registry"?"registered":"legacy",valid=[];for(let path3 of paths){if(hasBrainJson(path3,deps)){valid.push(path3);continue}warn(` Brain server: skipped ${label} vault ${path3} (missing brain.json)`)}return valid}function normalizeAndDedupe(paths,deps){return dedupeBrainVaultPaths(paths.map((path3)=>normalizeBrainVaultPath(path3,deps)),deps)}function pushPathFromEntry(entry2,paths){let found=!1;for(let field of REGISTRY_PATH_FIELDS){let value=entry2[field];if(typeof value==="string"&&value.trim().length>0)paths.push(value),found=!0}return found}function isRegistryRecord(value){return Boolean(value)&&typeof value==="object"&&!Array.isArray(value)}function collectRegistryArray(values2,paths){for(let item of values2)collectRegistryPaths(item,paths)}function collectRegistryObject(entry2,paths){let foundPath=pushPathFromEntry(entry2,paths);for(let field of REGISTRY_COLLECTION_FIELDS)if(field in entry2)collectRegistryPaths(entry2[field],paths);if(!foundPath){for(let item of Object.values(entry2))if(item&&typeof item==="object")collectRegistryPaths(item,paths)}}function collectRegistryPaths(value,paths){if(typeof value==="string"){if(value.trim().length>0)paths.push(value);return}if(Array.isArray(value)){collectRegistryArray(value,paths);return}if(isRegistryRecord(value))collectRegistryObject(value,paths)}function countRegistryItems(value,fallback){if(Array.isArray(value))return value.length;if(!isRegistryRecord(value))return fallback;for(let field of REGISTRY_COLLECTION_FIELDS){let collection=value[field];if(Array.isArray(collection))return collection.length;if(isRegistryRecord(collection))return Object.keys(collection).length}return fallback}async function discoverRegisteredBrainVaultPaths(deps){let brain=deps.brain;if(!brain)return{paths:[],registryCount:0};let registryCalls=["listBrains","listBrainVaults","listVaults","listRegisteredBrains","listRegisteredBrainVaults","getBrainRegistry","readBrainRegistry"];for(let name of registryCalls){let read=brain[name];if(typeof read!=="function")continue;try{let result2=await read.call(brain),paths=[];if(collectRegistryPaths(result2,paths),paths.length>0)return{paths,registryCount:countRegistryItems(result2,paths.length)}}catch(err){let msg=err instanceof Error?err.message:String(err);(deps.warn??console.warn)(` Brain registry: ${name} failed: ${msg}`)}}return{paths:[],registryCount:0}}async function findLegacyBrainVault(deps={}){let cwd=getCwd(deps),homeDir=getHomeDir(deps),workspaceRoot=getWorkspaceRoot(deps),candidates=[workspaceRoot?join52(workspaceRoot,"brain"):void 0,cwd,join52(cwd,"brain"),join52(homeDir,"brain")].filter((path3)=>typeof path3==="string");for(let path3 of normalizeAndDedupe(candidates,deps))if(hasBrainJson(path3,deps))return path3;return null}async function findBrainVault(deps={}){return(await resolveBrainVaults(deps)).paths[0]??null}async function resolveBrainVaults(deps={}){let configuredPaths=getConfig(deps).brain?.paths;if(Array.isArray(configuredPaths)&&configuredPaths.length>0)return{source:"config",paths:filterVaultsWithBrainJson(normalizeAndDedupe(configuredPaths,deps),"config",deps)};let registered=await discoverRegisteredBrainVaultPaths(deps);if(registered.paths.length>0)return{source:"registry",paths:filterVaultsWithBrainJson(normalizeAndDedupe(registered.paths,deps),"registry",deps),registryCount:registered.registryCount};let legacyPath=await findLegacyBrainVault(deps);return{source:"legacy",paths:legacyPath?[legacyPath]:[]}}function normalizeStartupConcurrency(value){if(typeof value!=="number"||!Number.isFinite(value))return DEFAULT_BRAIN_START_CONCURRENCY;return Math.max(1,Math.floor(value))}async function allSettledBounded(items,concurrency,worker){let results=Array(items.length),nextIndex=0;async function runWorker(){while(!0){let index=nextIndex++;if(index>=items.length)return;try{results[index]={status:"fulfilled",value:await worker(items[index],index)}}catch(reason){results[index]={status:"rejected",reason}}}}return await Promise.allSettled(Array.from({length:Math.min(concurrency,items.length)},()=>runWorker())),results}function warnRegistryDrift(resolution,startedCount,resolvedCount,deps){if(resolution.source!=="registry")return;let expectedCount=resolution.registryCount??resolvedCount;if(startedCount===expectedCount)return;(deps.warn??console.warn)(` Brain server: registry drift: started ${startedCount}/${expectedCount} registered vault(s) (${resolvedCount} resolved valid path(s))`)}async function startResolvedBrainVaults(resolution,brain,geniePgPort,deps={}){let startEmbeddedBrainServer=brain.startEmbeddedBrainServer;if(!startEmbeddedBrainServer)return[];let warn=deps.warn??console.warn,log2=deps.log??console.log,handles=[],paths=dedupeBrainVaultPaths(resolution.paths,deps),concurrency=normalizeStartupConcurrency(deps.startupConcurrency),results=await allSettledBounded(paths,concurrency,async(brainPath)=>{let handle=await startEmbeddedBrainServer.call(brain,{brainPath,geniePgPort});return log2(` Brain server ready on port ${handle.port} (${brainPath})`),{brainPath,port:handle.port,stop:handle.stop}});for(let index=0;index<results.length;index++){let result2=results[index];if(result2.status==="fulfilled")handles.push(result2.value);else{let msg=result2.reason instanceof Error?result2.reason.message:String(result2.reason);warn(` Brain server: failed for ${paths[index]}: ${msg}`)}}return warnRegistryDrift(resolution,handles.length,paths.length,deps),handles}var REGISTRY_PATH_FIELDS,REGISTRY_COLLECTION_FIELDS,DEFAULT_BRAIN_START_CONCURRENCY=4;var init_brain_vaults=__esm(()=>{init_genie_config2();init_workspace();REGISTRY_PATH_FIELDS=["homePath","brainPath","vaultPath","path","root","dir"],REGISTRY_COLLECTION_FIELDS=["paths","brains","vaults","entries","items","registered"]});var exports_tui_disable={};__export(exports_tui_disable,{noticeTuiSkipped:()=>noticeTuiSkipped,isTuiDisabled:()=>isTuiDisabled});function isTuiDisabled(){let envVal=process.env.GENIE_TUI_DISABLE;if(envVal&&TRUTHY2.has(envVal.trim().toLowerCase()))return!0;if(process.argv.includes("--no-tui"))return!0;if(process.stdout.isTTY===!1)return!0;return!1}function noticeTuiSkipped(context){let reason=process.env.GENIE_TUI_DISABLE?"GENIE_TUI_DISABLE is set":"--no-tui flag present";console.error(`genie: TUI ${context} skipped (${reason}). See https://github.com/automagik-dev/genie for status of the upstream OpenTUI kqueue spin on macOS.`)}var TRUTHY2;var init_tui_disable=__esm(()=>{TRUTHY2=new Set(["1","true","yes","on"])});var exports_service_registry={};__export(exports_service_registry,{unregisterService:()=>unregisterService,registerService:()=>registerService,reapDeadServices:()=>reapDeadServices,killAllServices:()=>killAllServices,getRegisteredServices:()=>getRegisteredServices,clearRegistry:()=>clearRegistry});function registerService(name,pid){registry.set(name,{pid,name,startedAt:new Date})}function unregisterService(name){registry.delete(name)}function getRegisteredServices(){return Array.from(registry.values())}function reapDeadServices(){let reaped=[];for(let[name,entry2]of registry)try{process.kill(entry2.pid,0)}catch{registry.delete(name),reaped.push(name)}return reaped}function killAllServices(){for(let[_name,entry2]of registry)try{process.kill(entry2.pid,"SIGTERM")}catch{registry.delete(_name)}let deadline=Date.now()+3000,checkInterval=200,stillAlive=()=>{for(let[,entry2]of registry)try{return process.kill(entry2.pid,0),!0}catch{}return!1};while(Date.now()<deadline&&stillAlive()){let waitUntil=Date.now()+checkInterval;while(Date.now()<waitUntil);}for(let[name,entry2]of registry){try{process.kill(entry2.pid,0),process.kill(entry2.pid,"SIGKILL")}catch{}registry.delete(name)}}function clearRegistry(){registry.clear()}var registry;var init_service_registry=__esm(()=>{registry=new Map});function parseDuration(input){let match=input.trim().match(DURATION_RE);if(!match)throw Error(`Invalid duration: "${input}". Expected format: 10m, 2h, 24h, 1d`);let value=Number.parseFloat(match[1]),unit=match[2].toLowerCase(),ms=value*{s:1000,sec:1000,m:60000,min:60000,h:3600000,hr:3600000,d:86400000,day:86400000}[unit];if(ms<=0)throw Error(`Duration must be positive: "${input}"`);return ms}function expandRange(range,step,min,max){if(step===0)throw Error("Cron step value cannot be 0");if(range==="*"){let out=[];for(let i2=min;i2<=max;i2+=step)out.push(i2);return out}if(range.includes("-")){let[start,end]=range.split("-").map(Number),out=[];for(let i2=start;i2<=end;i2+=step)out.push(i2);return out}return[Number.parseInt(range,10)]}function parseCronField(field,min,max){let values2=new Set;for(let part of field.split(",")){let stepMatch=part.match(/^(.+)\/(\d+)$/),step=stepMatch?Number.parseInt(stepMatch[2],10):1,range=stepMatch?stepMatch[1]:part;for(let v of expandRange(range,step,min,max))values2.add(v)}return[...values2].sort((a,b2)=>a-b2)}function getTimeParts(date,tz){if(!tz)return{month:date.getMonth()+1,dom:date.getDate(),dow:date.getDay(),hour:date.getHours(),minute:date.getMinutes()};let parts=new Intl.DateTimeFormat("en-US",{timeZone:tz,year:"numeric",month:"numeric",day:"numeric",hour:"numeric",minute:"numeric",weekday:"short",hour12:!1}).formatToParts(date),get3=(type2)=>Number(parts.find((p)=>p.type===type2)?.value??0),dayMap={Sun:0,Mon:1,Tue:2,Wed:3,Thu:4,Fri:5,Sat:6},weekday=parts.find((p)=>p.type==="weekday")?.value??"Sun";return{month:get3("month"),dom:get3("day"),dow:dayMap[weekday]??0,hour:get3("hour")===24?0:get3("hour"),minute:get3("minute")}}function parseOpts(afterOrOpts){if(afterOrOpts instanceof Date)return{after:afterOrOpts};if(afterOrOpts)return{after:afterOrOpts.after,timezone:afterOrOpts.timezone};return{}}function advanceToNextDay(candidate,tz){candidate.setTime(candidate.getTime()+86400000);let tp=getTimeParts(candidate,tz);candidate.setTime(candidate.getTime()-tp.hour*3600000-tp.minute*60000)}function parseCronExpr(cronExpr){let parts=cronExpr.trim().split(/\s+/);if(parts.length<5)throw Error(`Invalid cron expression: "${cronExpr}"`);let[minField,hourField,domField,monthField,dowField]=parts;return{minutes:parseCronField(minField,0,59),hours:parseCronField(hourField,0,23),doms:parseCronField(domField,1,31),months:parseCronField(monthField,1,12),dows:parseCronField(dowField,0,6),domRestricted:domField!=="*",dowRestricted:dowField!=="*"}}function computeNextCronDue(cronExpr,afterOrOpts){let{after,timezone}=parseOpts(afterOrOpts),cron=parseCronExpr(cronExpr),candidate=new Date((after??new Date).getTime());candidate.setSeconds(0,0),candidate.setTime(candidate.getTime()+60000);let limit=new Date(candidate.getTime()+31622400000);while(candidate<=limit){let tp=getTimeParts(candidate,timezone);if(!cron.months.includes(tp.month)){advanceToNextDay(candidate,timezone);continue}if(!(cron.domRestricted&&cron.dowRestricted?cron.doms.includes(tp.dom)||cron.dows.includes(tp.dow):cron.doms.includes(tp.dom)&&cron.dows.includes(tp.dow))){advanceToNextDay(candidate,timezone);continue}if(!cron.hours.includes(tp.hour)){candidate.setTime(candidate.getTime()+3600000-tp.minute*60000);continue}if(cron.minutes.includes(tp.minute))return candidate;candidate.setTime(candidate.getTime()+60000)}throw Error(`No next cron occurrence found for "${cronExpr}" within 366 days`)}var DURATION_RE;var init_cron=__esm(()=>{DURATION_RE=/^(\d+(?:\.\d+)?)\s*(s|sec|m|min|h|hr|d|day)s?$/i});import{randomUUID as randomUUID7}from"crypto";function parseNotifyPayload(channel,raw){switch(channel){case"genie_task_stage":{let parts=raw.split(":");if(parts.length<3)return null;return{channel,eventType:"task.stage_change",payload:{taskId:parts[0],fromStage:parts[1],toStage:parts[2]},taskId:parts[0],summary:`Task ${parts[0]} moved from ${parts[1]} to ${parts[2]}`}}case"genie_executor_state":{let parts=raw.split(":");if(parts.length<4)return null;let eventType=parts[3]==="error"?"executor.error":"executor.state_change";return{channel,eventType,payload:{executorId:parts[0],agentId:parts[1],oldState:parts[2],newState:parts[3]},agentId:parts[1],summary:`${parts[1]} state: ${parts[2]} \u2192 ${parts[3]}`}}case"genie_message":{let parts=raw.split(":");if(parts.length<2)return null;return{channel,eventType:"task.comment",payload:{messageId:parts[0],conversationId:parts[1]},summary:`New message in conversation ${parts[1]}`}}case"genie_audit_event":{let parts=raw.split(":");if(parts.length<3)return null;return{channel,eventType:`${parts[0]}.${parts[2]}`,payload:{entityType:parts[0],entityId:parts[1],auditEventType:parts[2]},summary:`${parts[0]} ${parts[1]}: ${parts[2]}`}}default:return null}}function isActionableEvent(eventType){return ACTIONABLE_EVENTS.has(eventType)||eventType.startsWith("request.")}async function resolveTargetTeams(event){if(!isActionableEvent(event.eventType))return[];let active=(await listTeams()).filter((t)=>t.status==="in_progress");if(event.agentId){let aid=event.agentId;return active.filter((t)=>t.members.includes(aid)||t.leader===aid).map((t)=>t.name)}return active.map((t)=>t.name)}async function writeMailbox(repoPath,leader,message,traceId){try{await(await getConnection())`
2165
+ ${body}`;writeFileSync16(filePath,output,"utf-8")}function serializeSdkConfig(sdk){let result2={};for(let[key,value]of Object.entries(sdk)){if(value===void 0||value===null)continue;if(Array.isArray(value)&&value.length===0)continue;if(typeof value==="object"&&!Array.isArray(value)&&Object.keys(value).length===0)continue;result2[key]=value}return result2}function splitFrontmatter(content){let match=content.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);if(!match)return{yamlObj:{},body:content};let yamlStr=match[1],body=match[2],yamlObj={};try{let parsed=load(yamlStr);if(typeof parsed==="object"&&parsed!==null)yamlObj=parsed}catch{}return{yamlObj,body}}function stripUndefined(obj){let result2={};for(let[key,value]of Object.entries(obj))if(value!==void 0)result2[key]=value;return result2}var init_frontmatter_writer=__esm(()=>{init_js_yaml()});import{existsSync as existsSync43,realpathSync as realpathSync5}from"fs";import{homedir as homedir34}from"os";import{join as join52,resolve as resolve7}from"path";function getCwd(deps){return deps.cwd??process.cwd()}function getHomeDir(deps){return deps.homeDir??homedir34()}function getWorkspaceRoot(deps){if("workspaceRoot"in deps)return deps.workspaceRoot??null;return findWorkspace()?.root??null}function getConfig(deps){return deps.config??loadGenieConfigSync()}function expandHome(path3,homeDir){if(path3==="~")return homeDir;if(path3.startsWith("~/"))return join52(homeDir,path3.slice(2));return path3}function normalizeBrainVaultPath(path3,deps){return resolve7(getCwd(deps),expandHome(path3,getHomeDir(deps)))}function canonicalBrainVaultPath(path3,deps){let realpath=deps.realpath??realpathSync5;try{return realpath(path3)}catch{return resolve7(path3)}}function dedupeBrainVaultPaths(paths,deps={}){let seen=new Set,deduped=[];for(let path3 of paths){let canonical=canonicalBrainVaultPath(path3,deps);if(seen.has(canonical))continue;seen.add(canonical),deduped.push(canonical)}return deduped}function hasBrainJson(path3,deps){return(deps.exists??existsSync43)(join52(path3,"brain.json"))}function filterVaultsWithBrainJson(paths,source,deps){let warn=deps.warn??console.warn,label=source==="config"?"configured":source==="registry"?"registered":"legacy",valid=[];for(let path3 of paths){if(hasBrainJson(path3,deps)){valid.push(path3);continue}warn(` Brain server: skipped ${label} vault ${path3} (missing brain.json)`)}return valid}function normalizeAndDedupe(paths,deps){return dedupeBrainVaultPaths(paths.map((path3)=>normalizeBrainVaultPath(path3,deps)),deps)}function pushPathFromEntry(entry2,paths){let found=!1;for(let field of REGISTRY_PATH_FIELDS){let value=entry2[field];if(typeof value==="string"&&value.trim().length>0)paths.push(value),found=!0}return found}function isRegistryRecord(value){return Boolean(value)&&typeof value==="object"&&!Array.isArray(value)}function collectRegistryArray(values2,paths){for(let item of values2)collectRegistryPaths(item,paths)}function collectRegistryObject(entry2,paths){let foundPath=pushPathFromEntry(entry2,paths);for(let field of REGISTRY_COLLECTION_FIELDS)if(field in entry2)collectRegistryPaths(entry2[field],paths);if(!foundPath){for(let item of Object.values(entry2))if(item&&typeof item==="object")collectRegistryPaths(item,paths)}}function collectRegistryPaths(value,paths){if(typeof value==="string"){if(value.trim().length>0)paths.push(value);return}if(Array.isArray(value)){collectRegistryArray(value,paths);return}if(isRegistryRecord(value))collectRegistryObject(value,paths)}function countRegistryItems(value,fallback){if(Array.isArray(value))return value.length;if(!isRegistryRecord(value))return fallback;for(let field of REGISTRY_COLLECTION_FIELDS){let collection=value[field];if(Array.isArray(collection))return collection.length;if(isRegistryRecord(collection))return Object.keys(collection).length}return fallback}async function discoverRegisteredBrainVaultPaths(deps){let brain=deps.brain;if(!brain)return{paths:[],registryCount:0};let registryCalls=["listBrains","listBrainVaults","listVaults","listRegisteredBrains","listRegisteredBrainVaults","getBrainRegistry","readBrainRegistry"];for(let name of registryCalls){let read=brain[name];if(typeof read!=="function")continue;try{let result2=await read.call(brain),paths=[];if(collectRegistryPaths(result2,paths),paths.length>0)return{paths,registryCount:countRegistryItems(result2,paths.length)}}catch(err){let msg=err instanceof Error?err.message:String(err);(deps.warn??console.warn)(` Brain registry: ${name} failed: ${msg}`)}}return{paths:[],registryCount:0}}async function findLegacyBrainVault(deps={}){let cwd=getCwd(deps),homeDir=getHomeDir(deps),workspaceRoot=getWorkspaceRoot(deps),candidates=[workspaceRoot?join52(workspaceRoot,"brain"):void 0,cwd,join52(cwd,"brain"),join52(homeDir,"brain")].filter((path3)=>typeof path3==="string");for(let path3 of normalizeAndDedupe(candidates,deps))if(hasBrainJson(path3,deps))return path3;return null}async function findBrainVault(deps={}){return(await resolveBrainVaults(deps)).paths[0]??null}async function resolveBrainVaults(deps={}){let configuredPaths=getConfig(deps).brain?.paths;if(Array.isArray(configuredPaths)&&configuredPaths.length>0)return{source:"config",paths:filterVaultsWithBrainJson(normalizeAndDedupe(configuredPaths,deps),"config",deps)};let registered=await discoverRegisteredBrainVaultPaths(deps);if(registered.paths.length>0)return{source:"registry",paths:filterVaultsWithBrainJson(normalizeAndDedupe(registered.paths,deps),"registry",deps),registryCount:registered.registryCount};let legacyPath=await findLegacyBrainVault(deps);return{source:"legacy",paths:legacyPath?[legacyPath]:[]}}function normalizeStartupConcurrency(value){if(typeof value!=="number"||!Number.isFinite(value))return DEFAULT_BRAIN_START_CONCURRENCY;return Math.max(1,Math.floor(value))}async function allSettledBounded(items,concurrency,worker){let results=Array(items.length),nextIndex=0;async function runWorker(){while(!0){let index=nextIndex++;if(index>=items.length)return;try{results[index]={status:"fulfilled",value:await worker(items[index],index)}}catch(reason){results[index]={status:"rejected",reason}}}}return await Promise.allSettled(Array.from({length:Math.min(concurrency,items.length)},()=>runWorker())),results}function warnRegistryDrift(resolution,startedCount,resolvedCount,deps){if(resolution.source!=="registry")return;let expectedCount=resolution.registryCount??resolvedCount;if(startedCount===expectedCount)return;(deps.warn??console.warn)(` Brain server: registry drift: started ${startedCount}/${expectedCount} registered vault(s) (${resolvedCount} resolved valid path(s))`)}async function startResolvedBrainVaults(resolution,brain,geniePgPort,deps={}){let startEmbeddedBrainServer=brain.startEmbeddedBrainServer;if(!startEmbeddedBrainServer)return[];let warn=deps.warn??console.warn,log2=deps.log??console.log,handles=[],paths=dedupeBrainVaultPaths(resolution.paths,deps),concurrency=normalizeStartupConcurrency(deps.startupConcurrency),results=await allSettledBounded(paths,concurrency,async(brainPath)=>{let handle=await startEmbeddedBrainServer.call(brain,{brainPath,geniePgPort});return log2(` Brain server ready on port ${handle.port} (${brainPath})`),{brainPath,port:handle.port,stop:handle.stop}});for(let index=0;index<results.length;index++){let result2=results[index];if(result2.status==="fulfilled")handles.push(result2.value);else{let msg=result2.reason instanceof Error?result2.reason.message:String(result2.reason);warn(` Brain server: failed for ${paths[index]}: ${msg}`)}}return warnRegistryDrift(resolution,handles.length,paths.length,deps),handles}var REGISTRY_PATH_FIELDS,REGISTRY_COLLECTION_FIELDS,DEFAULT_BRAIN_START_CONCURRENCY=4;var init_brain_vaults=__esm(()=>{init_genie_config2();init_workspace();REGISTRY_PATH_FIELDS=["homePath","brainPath","vaultPath","path","root","dir"],REGISTRY_COLLECTION_FIELDS=["paths","brains","vaults","entries","items","registered"]});var exports_tui_disable={};__export(exports_tui_disable,{noticeTuiSkipped:()=>noticeTuiSkipped,isTuiDisabled:()=>isTuiDisabled});function isTuiDisabled(){let envVal=process.env.GENIE_TUI_DISABLE;if(envVal&&TRUTHY2.has(envVal.trim().toLowerCase()))return!0;if(process.argv.includes("--no-tui"))return!0;if(!process.stdout.isTTY)return!0;return!1}function noticeTuiSkipped(context){let reason=process.env.GENIE_TUI_DISABLE?"GENIE_TUI_DISABLE is set":"--no-tui flag present";console.error(`genie: TUI ${context} skipped (${reason}). See https://github.com/automagik-dev/genie for status of the upstream OpenTUI kqueue spin on macOS.`)}var TRUTHY2;var init_tui_disable=__esm(()=>{TRUTHY2=new Set(["1","true","yes","on"])});var exports_service_registry={};__export(exports_service_registry,{unregisterService:()=>unregisterService,registerService:()=>registerService,reapDeadServices:()=>reapDeadServices,killAllServices:()=>killAllServices,getRegisteredServices:()=>getRegisteredServices,clearRegistry:()=>clearRegistry});function registerService(name,pid){registry.set(name,{pid,name,startedAt:new Date})}function unregisterService(name){registry.delete(name)}function getRegisteredServices(){return Array.from(registry.values())}function reapDeadServices(){let reaped=[];for(let[name,entry2]of registry)try{process.kill(entry2.pid,0)}catch{registry.delete(name),reaped.push(name)}return reaped}function killAllServices(){for(let[_name,entry2]of registry)try{process.kill(entry2.pid,"SIGTERM")}catch{registry.delete(_name)}let deadline=Date.now()+3000,checkInterval=200,stillAlive=()=>{for(let[,entry2]of registry)try{return process.kill(entry2.pid,0),!0}catch{}return!1};while(Date.now()<deadline&&stillAlive()){let waitUntil=Date.now()+checkInterval;while(Date.now()<waitUntil);}for(let[name,entry2]of registry){try{process.kill(entry2.pid,0),process.kill(entry2.pid,"SIGKILL")}catch{}registry.delete(name)}}function clearRegistry(){registry.clear()}var registry;var init_service_registry=__esm(()=>{registry=new Map});function parseDuration(input){let match=input.trim().match(DURATION_RE);if(!match)throw Error(`Invalid duration: "${input}". Expected format: 10m, 2h, 24h, 1d`);let value=Number.parseFloat(match[1]),unit=match[2].toLowerCase(),ms=value*{s:1000,sec:1000,m:60000,min:60000,h:3600000,hr:3600000,d:86400000,day:86400000}[unit];if(ms<=0)throw Error(`Duration must be positive: "${input}"`);return ms}function expandRange(range,step,min,max){if(step===0)throw Error("Cron step value cannot be 0");if(range==="*"){let out=[];for(let i2=min;i2<=max;i2+=step)out.push(i2);return out}if(range.includes("-")){let[start,end]=range.split("-").map(Number),out=[];for(let i2=start;i2<=end;i2+=step)out.push(i2);return out}return[Number.parseInt(range,10)]}function parseCronField(field,min,max){let values2=new Set;for(let part of field.split(",")){let stepMatch=part.match(/^(.+)\/(\d+)$/),step=stepMatch?Number.parseInt(stepMatch[2],10):1,range=stepMatch?stepMatch[1]:part;for(let v of expandRange(range,step,min,max))values2.add(v)}return[...values2].sort((a,b2)=>a-b2)}function getTimeParts(date,tz){if(!tz)return{month:date.getMonth()+1,dom:date.getDate(),dow:date.getDay(),hour:date.getHours(),minute:date.getMinutes()};let parts=new Intl.DateTimeFormat("en-US",{timeZone:tz,year:"numeric",month:"numeric",day:"numeric",hour:"numeric",minute:"numeric",weekday:"short",hour12:!1}).formatToParts(date),get3=(type2)=>Number(parts.find((p)=>p.type===type2)?.value??0),dayMap={Sun:0,Mon:1,Tue:2,Wed:3,Thu:4,Fri:5,Sat:6},weekday=parts.find((p)=>p.type==="weekday")?.value??"Sun";return{month:get3("month"),dom:get3("day"),dow:dayMap[weekday]??0,hour:get3("hour")===24?0:get3("hour"),minute:get3("minute")}}function parseOpts(afterOrOpts){if(afterOrOpts instanceof Date)return{after:afterOrOpts};if(afterOrOpts)return{after:afterOrOpts.after,timezone:afterOrOpts.timezone};return{}}function advanceToNextDay(candidate,tz){candidate.setTime(candidate.getTime()+86400000);let tp=getTimeParts(candidate,tz);candidate.setTime(candidate.getTime()-tp.hour*3600000-tp.minute*60000)}function parseCronExpr(cronExpr){let parts=cronExpr.trim().split(/\s+/);if(parts.length<5)throw Error(`Invalid cron expression: "${cronExpr}"`);let[minField,hourField,domField,monthField,dowField]=parts;return{minutes:parseCronField(minField,0,59),hours:parseCronField(hourField,0,23),doms:parseCronField(domField,1,31),months:parseCronField(monthField,1,12),dows:parseCronField(dowField,0,6),domRestricted:domField!=="*",dowRestricted:dowField!=="*"}}function computeNextCronDue(cronExpr,afterOrOpts){let{after,timezone}=parseOpts(afterOrOpts),cron=parseCronExpr(cronExpr),candidate=new Date((after??new Date).getTime());candidate.setSeconds(0,0),candidate.setTime(candidate.getTime()+60000);let limit=new Date(candidate.getTime()+31622400000);while(candidate<=limit){let tp=getTimeParts(candidate,timezone);if(!cron.months.includes(tp.month)){advanceToNextDay(candidate,timezone);continue}if(!(cron.domRestricted&&cron.dowRestricted?cron.doms.includes(tp.dom)||cron.dows.includes(tp.dow):cron.doms.includes(tp.dom)&&cron.dows.includes(tp.dow))){advanceToNextDay(candidate,timezone);continue}if(!cron.hours.includes(tp.hour)){candidate.setTime(candidate.getTime()+3600000-tp.minute*60000);continue}if(cron.minutes.includes(tp.minute))return candidate;candidate.setTime(candidate.getTime()+60000)}throw Error(`No next cron occurrence found for "${cronExpr}" within 366 days`)}var DURATION_RE;var init_cron=__esm(()=>{DURATION_RE=/^(\d+(?:\.\d+)?)\s*(s|sec|m|min|h|hr|d|day)s?$/i});import{randomUUID as randomUUID7}from"crypto";function parseNotifyPayload(channel,raw){switch(channel){case"genie_task_stage":{let parts=raw.split(":");if(parts.length<3)return null;return{channel,eventType:"task.stage_change",payload:{taskId:parts[0],fromStage:parts[1],toStage:parts[2]},taskId:parts[0],summary:`Task ${parts[0]} moved from ${parts[1]} to ${parts[2]}`}}case"genie_executor_state":{let parts=raw.split(":");if(parts.length<4)return null;let eventType=parts[3]==="error"?"executor.error":"executor.state_change";return{channel,eventType,payload:{executorId:parts[0],agentId:parts[1],oldState:parts[2],newState:parts[3]},agentId:parts[1],summary:`${parts[1]} state: ${parts[2]} \u2192 ${parts[3]}`}}case"genie_message":{let parts=raw.split(":");if(parts.length<2)return null;return{channel,eventType:"task.comment",payload:{messageId:parts[0],conversationId:parts[1]},summary:`New message in conversation ${parts[1]}`}}case"genie_audit_event":{let parts=raw.split(":");if(parts.length<3)return null;return{channel,eventType:`${parts[0]}.${parts[2]}`,payload:{entityType:parts[0],entityId:parts[1],auditEventType:parts[2]},summary:`${parts[0]} ${parts[1]}: ${parts[2]}`}}default:return null}}function isActionableEvent(eventType){return ACTIONABLE_EVENTS.has(eventType)||eventType.startsWith("request.")}async function resolveTargetTeams(event){if(!isActionableEvent(event.eventType))return[];let active=(await listTeams()).filter((t)=>t.status==="in_progress");if(event.agentId){let aid=event.agentId;return active.filter((t)=>t.members.includes(aid)||t.leader===aid).map((t)=>t.name)}return active.map((t)=>t.name)}async function writeMailbox(repoPath,leader,message,traceId){try{await(await getConnection())`
2136
2166
  INSERT INTO mailbox (id, repo_path, "from", "to", body, trace_id, created_at)
2137
2167
  VALUES (${`mail-${traceId}`}, ${repoPath}, 'system', ${leader}, ${message}, ${traceId}, now())
2138
2168
  `}catch{try{await send(repoPath,"system",leader,message)}catch{}}}async function deliverToHierarchy(leader,teamName,message,traceId){let sql=await getConnection(),current=leader,visited=new Set([current]);for(;;){let reportsTo=(await sql`
@@ -4547,7 +4577,57 @@ Exit codes:
4547
4577
 
4548
4578
  Must return exit 0 before 'genie sec remediate --apply' will proceed. See
4549
4579
  docs/incident-response/canisterworm.md for the legitimate --unsafe-unverified contexts.
4550
- `.trimStart()).action((options)=>{let exitCode=runVerifyInstallCommand(options,deps);applySecScanExitCode(exitCode,deps)})}init_serve();init_db();init_session_backfill();init_term_format();function resolveAgentLabel(r){if(r.agent_name)return r.agent_name;if(r.executor_id)return r.executor_id.slice(0,12);if(r.agent_id)return r.agent_id;return"(orphaned)"}async function sessionsListCommand(options){if(!await isAvailable())console.error("Database not available."),process.exit(1);let sql=await getConnection(),limit=Number(options.limit)||50,sourceFilter=options.source?sql`AND e.metadata->>'source' = ${options.source}`:sql``,rows;if(options.active)rows=await sql`
4580
+ `.trimStart()).action((options)=>{let exitCode=runVerifyInstallCommand(options,deps);applySecScanExitCode(exitCode,deps)})}init_serve();init_db();init_session_backfill();async function diagnoseSessionLinks(sql){let[linkableOrphanRow]=await sql`
4581
+ SELECT count(*)::int AS n
4582
+ FROM sessions s
4583
+ JOIN executors e ON s.id = e.claude_session_id
4584
+ WHERE s.executor_id IS NULL
4585
+ `,[sessionRow]=await sql`
4586
+ SELECT
4587
+ count(*)::int AS total,
4588
+ count(*) FILTER (WHERE status = 'orphaned')::int AS status_orphaned,
4589
+ count(*) FILTER (WHERE executor_id IS NULL)::int AS null_executor,
4590
+ count(*) FILTER (WHERE team = '')::int AS empty_team,
4591
+ count(*) FILTER (WHERE wish_slug = '')::int AS empty_wish_slug,
4592
+ count(*) FILTER (WHERE role = '')::int AS empty_role
4593
+ FROM sessions
4594
+ `,[toolEventRow]=await sql`
4595
+ SELECT
4596
+ count(*)::int AS total,
4597
+ count(*) FILTER (WHERE agent_id IS NULL OR agent_id = '')::int AS missing_agent,
4598
+ count(*) FILTER (WHERE team IS NULL OR team = '')::int AS missing_team,
4599
+ count(*) FILTER (WHERE wish_slug IS NULL OR wish_slug = '')::int AS missing_wish,
4600
+ count(*) FILTER (WHERE task_id IS NULL OR task_id = '')::int AS missing_task,
4601
+ count(*) FILTER (WHERE agent_id = '')::int AS empty_agent,
4602
+ count(*) FILTER (WHERE team = '')::int AS empty_team,
4603
+ count(*) FILTER (WHERE wish_slug = '')::int AS empty_wish,
4604
+ count(*) FILTER (WHERE task_id = '')::int AS empty_task
4605
+ FROM tool_events
4606
+ `,[linkableTeRow]=await sql`
4607
+ SELECT count(*)::int AS n
4608
+ FROM tool_events te
4609
+ JOIN sessions s ON s.id = te.session_id
4610
+ WHERE s.executor_id IS NOT NULL
4611
+ AND (
4612
+ (te.agent_id IS NULL OR te.agent_id = '') OR
4613
+ (te.team IS NULL OR te.team = '') OR
4614
+ (te.wish_slug IS NULL OR te.wish_slug = '') OR
4615
+ (te.task_id IS NULL OR te.task_id = '')
4616
+ )
4617
+ `;return{linkableOrphanSessions:Number(linkableOrphanRow?.n??0),totalSessions:Number(sessionRow?.total??0),statusOrphanedSessions:Number(sessionRow?.status_orphaned??0),nullExecutorIdSessions:Number(sessionRow?.null_executor??0),sessionsEmptyStringTeam:Number(sessionRow?.empty_team??0),sessionsEmptyStringWishSlug:Number(sessionRow?.empty_wish_slug??0),sessionsEmptyStringRole:Number(sessionRow?.empty_role??0),totalToolEvents:Number(toolEventRow?.total??0),toolEventsMissingAgent:Number(toolEventRow?.missing_agent??0),toolEventsMissingTeam:Number(toolEventRow?.missing_team??0),toolEventsMissingWish:Number(toolEventRow?.missing_wish??0),toolEventsMissingTask:Number(toolEventRow?.missing_task??0),toolEventsEmptyStringAgent:Number(toolEventRow?.empty_agent??0),toolEventsEmptyStringTeam:Number(toolEventRow?.empty_team??0),toolEventsEmptyStringWish:Number(toolEventRow?.empty_wish??0),toolEventsEmptyStringTask:Number(toolEventRow?.empty_task??0),toolEventsLinkableMissingAttribution:Number(linkableTeRow?.n??0)}}async function sampleLinkableOrphanSessions(sql,limit=20){return(await sql`
4618
+ SELECT s.id AS session_id, e.id AS executor_id, e.agent_id, s.status
4619
+ FROM sessions s
4620
+ JOIN executors e ON s.id = e.claude_session_id
4621
+ WHERE s.executor_id IS NULL
4622
+ ORDER BY s.created_at DESC NULLS LAST
4623
+ LIMIT ${limit}
4624
+ `).map((r)=>({sessionId:r.session_id,executorId:r.executor_id,agentId:r.agent_id,status:r.status}))}async function findAmbiguousExecutorSessions(sql){return(await sql`
4625
+ SELECT claude_session_id, array_agg(id) AS executor_ids
4626
+ FROM executors
4627
+ WHERE claude_session_id IS NOT NULL
4628
+ GROUP BY claude_session_id
4629
+ HAVING count(*) > 1
4630
+ `).map((r)=>({claudeSessionId:r.claude_session_id,executorIds:r.executor_ids}))}init_term_format();function resolveAgentLabel(r){if(r.agent_name)return r.agent_name;if(r.executor_id)return r.executor_id.slice(0,12);if(r.agent_id)return r.agent_id;return"(orphaned)"}async function sessionsListCommand(options){if(!await isAvailable())console.error("Database not available."),process.exit(1);let sql=await getConnection(),limit=Number(options.limit)||50,sourceFilter=options.source?sql`AND e.metadata->>'source' = ${options.source}`:sql``,rows;if(options.active)rows=await sql`
4551
4631
  SELECT s.*, a.custom_name as agent_name
4552
4632
  FROM sessions s
4553
4633
  LEFT JOIN executors e ON s.executor_id = e.id
@@ -4609,7 +4689,55 @@ docs/incident-response/canisterworm.md for the legitimate --unsafe-unverified co
4609
4689
  ORDER BY sc.timestamp DESC
4610
4690
  LIMIT ${limit}
4611
4691
  `;if(options.json){console.log(JSON.stringify(rows,null,2));return}if(rows.length===0){console.log(`No results for "${query2}".`);return}for(let r of rows)console.log(`[${formatRelativeTimestamp(r.timestamp)}] ${r.agent_label??"orphaned"} / ${r.session_id.slice(0,12)}`),console.log(` ${r.role}${r.tool_name?` [${r.tool_name}]`:""}: ${r.headline}`);console.log(`
4612
- (${rows.length} result${rows.length===1?"":"s"})`)}async function sessionsSyncStatusCommand(){if(!await isAvailable())console.error("Database not available."),process.exit(1);let sql=await getConnection(),status=await getBackfillStatus(sql);if(!status){console.log("No backfill has been started. It runs automatically on first daemon start.");return}let pct=status.totalFiles>0?(status.processedFiles/status.totalFiles*100).toFixed(1):"0.0",mbRead=(status.processedBytes/1024/1024).toFixed(1),mbTotal=(status.totalBytes/1024/1024).toFixed(1);console.log(`Session backfill: ${status.processedFiles} / ${status.totalFiles} files (${pct}%)`),console.log(`Bytes read: ${mbRead} MB / ${mbTotal} MB`),console.log(`Errors: ${status.errors}`),console.log(`Status: ${status.status}`)}function registerSessionsCommands(program2){let sessions2=program2.command("sessions").description("Session history \u2014 list, replay, search");sessions2.command("list",{isDefault:!0}).description("List Claude Code sessions").option("--active","Show only active sessions").option("--orphaned","Show only orphaned sessions").option("--agent <name>","Filter by agent").option("--source <name>","Filter by executor metadata source (e.g. omni)").option("--limit <n>","Max number of sessions to return (default: 50)").option("--json","Output as JSON").action(async(options)=>{await sessionsListCommand(options)}),sessions2.command("replay <session-id>").description("Replay a session \u2014 interleave content + events").option("--json","Output as JSON").action(async(sessionId,options)=>{await sessionsReplayCommand(sessionId,options)}),sessions2.command("search <query>").description("Full-text search across session content").option("--json","Output as JSON").option("--limit <n>","Max results","20").action(async(query2,options)=>{await sessionsSearchCommand(query2,options)}),sessions2.command("sync").description("Check session backfill progress").action(async()=>{await sessionsSyncStatusCommand()})}init_state();init_observability_health();init_agent_registry();init_agent_registry();init_derived_signals();init_derived_signals();init_executor_registry();init_should_resume();init_term_format();var ANSI2={reset:"\x1B[0m",dim:"\x1B[2m",bold:"\x1B[1m",red:"\x1B[31m",green:"\x1B[32m",yellow:"\x1B[33m",cyan:"\x1B[36m",magenta:"\x1B[35m"};function colorize(text,color2){if(process.env.NO_COLOR||!process.stdout.isTTY)return text;return`${ANSI2[color2]}${text}${ANSI2.reset}`}async function aggregateAgentDecisions(includeArchived){let agents=await listAgentsForRender({includeArchived}),results=Array(agents.length),cursor=0,cap=Math.min(BOOT_PASS_CONCURRENCY_CAP,Math.max(1,agents.length)),workers=Array.from({length:cap},async()=>{while(cursor<agents.length){let i2=cursor++;if(i2>=agents.length)return;let a=agents[i2],decision=await shouldResume(a.id).catch(()=>({resume:!1,reason:"no_session_id",rehydrate:"lazy"})),name=a.customName??a.role??a.id,sessionPreview=decision.sessionId?decision.sessionId.slice(0,8):null,lastWriteAt=null;if(a.currentExecutorId){let exec3=await getExecutor(a.currentExecutorId).catch(()=>null);lastWriteAt=exec3?.updatedAt??exec3?.startedAt??null}results[i2]={agentId:a.id,name,kind:a.kind??null,decision,sessionPreview,lastWriteAt}}});return await Promise.all(workers),results}async function collectHealthChecks(){let report2=await collectObservabilityHealth();return[{name:"partition",status:report2.partition_health,message:report2.next_rotation_at?`next rotation: ${report2.next_rotation_at}`:void 0},{name:"watchdog",status:report2.watchdog,message:report2.watchdog_detail},{name:"spill journal",status:report2.spill_journal==="pending"?"warn":report2.spill_journal==="unknown"?"unknown":"ok",message:report2.spill_path},{name:"watcher metrics",status:report2.watcher_metrics,message:report2.watcher_metrics==="ok"?"all six recently seen":"one or more meta-events missing"}]}function statusIcon(status){switch(status){case"ok":return colorize("\u2713","green");case"warn":return colorize("!","yellow");case"fail":return colorize("\u2717","red");default:return colorize("?","dim")}}function severityBadge(sev){if(sev==="critical")return colorize("[CRITICAL]","red");if(sev==="warn")return colorize("[WARN]","yellow");return colorize("[INFO]","dim")}function formatAgentLine(line){let kindTag=line.kind==="permanent"?colorize("p","magenta"):colorize("t","cyan"),session=line.sessionPreview?colorize(line.sessionPreview,"dim"):colorize("no-session","yellow"),lastWrite=line.lastWriteAt?formatRelativeTimestamp(line.lastWriteAt):"-",reason=line.decision.reason==="ok"?colorize("resume ready","green"):colorize(line.decision.reason,"yellow");return` [${kindTag}] ${line.name.padEnd(28).slice(0,28)} ${session.padEnd(8)} last:${lastWrite.padEnd(10)} ${reason}`}function renderResumableSection(lines){let resumable=lines.filter((l)=>l.decision.resume);if(resumable.length===0){console.log(colorize(" (no in-flight agents \u2014 every prior anchor is closed or paused)","dim"));return}for(let line of resumable)console.log(formatAgentLine(line))}function renderStuckSection(lines){let stuck=lines.filter((l)=>!l.decision.resume&&l.decision.reason!=="assignment_closed"&&l.decision.reason!=="unknown_agent");if(stuck.length===0)return;console.log(""),console.log(colorize("STUCK / NEEDS ATTENTION","bold")),console.log("-".repeat(60));for(let line of stuck)if(console.log(formatAgentLine(line)),line.decision.reason==="auto_resume_disabled")console.log(colorize(` \u2192 genie agent resume ${line.name}`,"dim"));else if(line.decision.reason==="no_session_id")console.log(colorize(` \u2192 genie agent show ${line.name} # inspect; consider archive`,"dim"))}function renderArchivedSection(lines){let done=lines.filter((l)=>l.decision.reason==="assignment_closed");if(done.length===0)return;console.log(""),console.log(colorize("DONE / ARCHIVED","bold")),console.log("-".repeat(60));for(let line of done)console.log(formatAgentLine(line))}function renderSignalsSection(signals2){if(signals2.length===0){console.log(colorize(" (no active alerts)","dim"));return}for(let sig of signals2){console.log(` ${severityBadge(sig.severity)} ${colorize(sig.type,"bold")} on ${sig.subject}`);let drilldown=SIGNAL_DRILLDOWN[sig.type];if(drilldown)console.log(colorize(` \u2192 ${drilldown}`,"dim"));if(sig.triggeredAt)console.log(colorize(` ${formatRelativeTimestamp(sig.triggeredAt)}`,"dim"))}}function renderHealthSection(checks){for(let check2 of checks){let detail=check2.message?colorize(` ${check2.message}`,"dim"):"";console.log(` ${statusIcon(check2.status)} ${check2.name.padEnd(18)} ${detail}`)}}async function renderDebugSection(){let audit=await auditAgentKind();if(console.log(""),console.log(colorize("DEBUG \u2014 kind audit","bold")),console.log("-".repeat(60)),console.log(` rows scanned: ${audit.total}`),console.log(` drift count : ${audit.drifted.length}`),audit.drifted.length>0)for(let d of audit.drifted.slice(0,10))console.log(colorize(` drift: ${d.id} stored=${d.kind??"null"} expected=${d.expected}`,"yellow"))}async function buildReport(opts){let includeArchived=opts.all===!0,[agents,signals2]=await Promise.all([aggregateAgentDecisions(includeArchived),listActiveDerivedSignals()]),partitionSignal=await detectPartitionMissing().catch(()=>null);if(partitionSignal)await recordDerivedSignal(partitionSignal).catch(()=>{}),signals2.unshift(partitionSignal);let report2={agents,signals:signals2};if(opts.health)report2.health=await collectHealthChecks();return report2}async function statusCommand2(opts={}){let t0=Date.now(),report2=await buildReport(opts);if(opts.json){console.log(JSON.stringify(report2,null,2));return}if(console.log(""),console.log(colorize("IN-FLIGHT \u2014 should resume","bold")),console.log("-".repeat(60)),renderResumableSection(report2.agents),renderStuckSection(report2.agents),opts.all)renderArchivedSection(report2.agents);if(console.log(""),console.log(colorize("ACTIVE SIGNALS","bold")),console.log("-".repeat(60)),renderSignalsSection(report2.signals),report2.health)console.log(""),console.log(colorize("HEALTH","bold")),console.log("-".repeat(60)),renderHealthSection(report2.health);if(opts.debug)await renderDebugSection();console.log(""),console.log(colorize(` rendered in ${Date.now()-t0}ms \u2014 ${report2.agents.length} agents, ${report2.signals.length} signals`,"dim")),console.log("")}init_genie_tokens();init_term_format();var _taskService7;async function getTaskService7(){if(!_taskService7)_taskService7=await Promise.resolve().then(() => (init_task_service(),exports_task_service));return _taskService7}function registerTagCommands(program2){let tag=program2.command("tag").description("Tag management");tag.command("list").description("List all tags").option("--type <typeId>","Filter by task type").option("--json","Output as JSON").action(async(options)=>{try{let tags=await(await getTaskService7()).listTags(options.type);if(options.json){console.log(JSON.stringify(tags,null,2));return}console.log(` ${padRight("ID",20)} ${padRight("NAME",20)} ${padRight("COLOR",10)} TYPE`),console.log(` ${"\u2500".repeat(55)}`);for(let t of tags)console.log(` ${padRight(t.id,20)} ${padRight(t.name,20)} ${padRight(t.color,10)} ${t.typeId??"-"}`);console.log(`
4692
+ (${rows.length} result${rows.length===1?"":"s"})`)}function printRepairDiagnostics(diag,sample,ambiguous){if(console.log("Sessions:"),console.log(` total: ${diag.totalSessions}`),console.log(` linkable orphans (sessions.id = executors.claude_session_id \u2227 executor_id IS NULL): ${diag.linkableOrphanSessions}`),console.log(` status='orphaned': ${diag.statusOrphanedSessions}`),console.log(` NULL executor_id: ${diag.nullExecutorIdSessions}`),console.log("Tool events:"),console.log(` total: ${diag.totalToolEvents}`),console.log(` missing agent_id (NULL or ''): ${diag.toolEventsMissingAgent}`),console.log(` missing team (NULL or ''): ${diag.toolEventsMissingTeam}`),console.log(` missing wish_slug (NULL or ''): ${diag.toolEventsMissingWish}`),console.log(` missing task_id (NULL or ''): ${diag.toolEventsMissingTask}`),console.log(` empty-string agent_id: ${diag.toolEventsEmptyStringAgent}`),console.log(` empty-string team: ${diag.toolEventsEmptyStringTeam}`),console.log(` empty-string wish_slug: ${diag.toolEventsEmptyStringWish}`),console.log(` empty-string task_id: ${diag.toolEventsEmptyStringTask}`),console.log(` linkable (session has executor_id, event missing attribution): ${diag.toolEventsLinkableMissingAttribution}`),sample.length>0){console.log(`
4693
+ Linkable orphan sample (up to 10):`);for(let s2 of sample)console.log(` ${s2.sessionId} executor=${s2.executorId.slice(0,12)} agent=${(s2.agentId??"-").slice(0,12)} status=${s2.status??"-"}`)}if(ambiguous.length>0){console.log(`
4694
+ \u26A0\uFE0F Ambiguous claude_session_id values (${ambiguous.length}) \u2014 multiple executors claim the same session id:`);for(let a of ambiguous)console.log(` ${a.claudeSessionId} -> ${a.executorIds.join(", ")}`);console.log(" --apply will refuse unless --force is passed.")}}function evaluateAmbiguityGate(ambiguousCount,force){if(ambiguousCount>0&&!force)return{blocked:!0,message:`repair-links: ${ambiguousCount} ambiguous claude_session_id value(s) found. Multiple executors claim the same session id \u2014 refusing --apply.
4695
+ Run with --dry-run to inspect, or pass --force to override.`};return{blocked:!1,message:null}}function buildNoWorkResultIfApplicable(diag,ambiguousCount,force){if(diag.linkableOrphanSessions===0&&diag.toolEventsLinkableMissingAttribution===0)return{sessionsLinked:0,toolEventsBackfilled:0,ambiguousCount,forced:force,driftDetected:!1};return null}async function applyRepairTransaction(sql,previewCount,force){let result2={sessionsLinked:0,toolEventsBackfilled:0,ambiguousCount:0,forced:force,driftDetected:!1};return await sql.begin(async(tx)=>{let[recount]=await tx`
4696
+ SELECT count(*)::int AS n
4697
+ FROM sessions s
4698
+ JOIN executors e ON s.id = e.claude_session_id
4699
+ WHERE s.executor_id IS NULL
4700
+ `;if(recount.n!==previewCount&&!force)throw result2.driftDetected=!0,Error(`repair-links: candidate count drifted between preview (${previewCount}) and apply (${recount.n}). Re-run --dry-run or pass --force to override.`);let linkResult=await tx`
4701
+ UPDATE sessions s SET
4702
+ executor_id = e.id,
4703
+ agent_id = COALESCE(s.agent_id, e.agent_id),
4704
+ team = COALESCE(s.team, a.team),
4705
+ wish_slug = COALESCE(s.wish_slug, a.wish_slug),
4706
+ task_id = COALESCE(s.task_id, a.task_id),
4707
+ role = COALESCE(s.role, a.role),
4708
+ status = CASE WHEN s.status = 'orphaned' THEN 'active' ELSE s.status END,
4709
+ updated_at = now()
4710
+ FROM executors e
4711
+ LEFT JOIN agents a ON e.agent_id = a.id
4712
+ WHERE s.id = e.claude_session_id
4713
+ AND s.executor_id IS NULL
4714
+ `,teResult=await tx`
4715
+ UPDATE tool_events te SET
4716
+ agent_id = COALESCE(NULLIF(te.agent_id, ''), s.agent_id),
4717
+ team = COALESCE(NULLIF(te.team, ''), s.team),
4718
+ wish_slug = COALESCE(NULLIF(te.wish_slug, ''), s.wish_slug),
4719
+ task_id = COALESCE(NULLIF(te.task_id, ''), s.task_id)
4720
+ FROM sessions s
4721
+ WHERE s.id = te.session_id
4722
+ AND s.executor_id IS NOT NULL
4723
+ AND (
4724
+ te.agent_id IS DISTINCT FROM COALESCE(NULLIF(te.agent_id, ''), s.agent_id) OR
4725
+ te.team IS DISTINCT FROM COALESCE(NULLIF(te.team, ''), s.team) OR
4726
+ te.wish_slug IS DISTINCT FROM COALESCE(NULLIF(te.wish_slug, ''), s.wish_slug) OR
4727
+ te.task_id IS DISTINCT FROM COALESCE(NULLIF(te.task_id, ''), s.task_id)
4728
+ )
4729
+ `;await tx`
4730
+ INSERT INTO audit_events (entity_type, entity_id, event_type, actor, details)
4731
+ VALUES (
4732
+ 'sessions',
4733
+ 'repair-links',
4734
+ 'sessions.repair_links',
4735
+ 'cli',
4736
+ ${tx.json({sessions_linked:linkResult.count??0,tool_events_backfilled:teResult.count??0,preview_count:previewCount,recount:recount.n,forced:force})}
4737
+ )
4738
+ `,result2={sessionsLinked:linkResult.count??0,toolEventsBackfilled:teResult.count??0,ambiguousCount:0,forced:force,driftDetected:!1}}),result2}function renderDryRun(diag,sample,ambiguous,json2){if(json2){console.log(JSON.stringify({diagnostics:diag,sample,ambiguous},null,2));return}if(console.log("repair-links --dry-run (no rows mutated)"),console.log("-----------------------------------------"),printRepairDiagnostics(diag,sample,ambiguous),diag.linkableOrphanSessions===0&&diag.toolEventsLinkableMissingAttribution===0)console.log(`
4739
+ Nothing to repair.`);else console.log(`
4740
+ Run with --apply to repair ${diag.linkableOrphanSessions} session(s) and up to ${diag.toolEventsLinkableMissingAttribution} tool_event(s).`)}function renderApplyResult(result2,json2){if(json2){console.log(JSON.stringify(result2,null,2));return}if(console.log("repair-links --apply complete"),console.log(` sessions linked: ${result2.sessionsLinked}`),console.log(` tool_events backfilled: ${result2.toolEventsBackfilled}`),result2.forced)console.log(" --force was used")}async function sessionsRepairLinksCommand(options){if(!await isAvailable())console.error("Database not available."),process.exit(1);let sql=await getConnection(),diag=await diagnoseSessionLinks(sql),sample=await sampleLinkableOrphanSessions(sql,10),ambiguous=await findAmbiguousExecutorSessions(sql);if(options.apply!==!0){renderDryRun(diag,sample,ambiguous,options.json===!0);return}let force=options.force===!0,ambiguityGate=evaluateAmbiguityGate(ambiguous.length,force);if(ambiguityGate.blocked)console.error(ambiguityGate.message),process.exit(2);let noWorkResult=buildNoWorkResultIfApplicable(diag,ambiguous.length,force);if(noWorkResult){if(options.json)console.log(JSON.stringify(noWorkResult,null,2));else console.log("repair-links: nothing to repair (0 candidates).");return}let result2;try{result2=await applyRepairTransaction(sql,diag.linkableOrphanSessions,options.force===!0)}catch(err){console.error(err.message),process.exit(2)}renderApplyResult(result2,options.json===!0)}async function sessionsSyncStatusCommand(){if(!await isAvailable())console.error("Database not available."),process.exit(1);let sql=await getConnection(),status=await getBackfillStatus(sql);if(!status){console.log("No backfill has been started. It runs automatically on first daemon start.");return}let pct=status.totalFiles>0?(status.processedFiles/status.totalFiles*100).toFixed(1):"0.0",mbRead=(status.processedBytes/1024/1024).toFixed(1),mbTotal=(status.totalBytes/1024/1024).toFixed(1);console.log(`Session backfill: ${status.processedFiles} / ${status.totalFiles} files (${pct}%)`),console.log(`Bytes read: ${mbRead} MB / ${mbTotal} MB`),console.log(`Errors: ${status.errors}`),console.log(`Status: ${status.status}`)}function registerSessionsCommands(program2){let sessions2=program2.command("sessions").description("Session history \u2014 list, replay, search");sessions2.command("list",{isDefault:!0}).description("List Claude Code sessions").option("--active","Show only active sessions").option("--orphaned","Show only orphaned sessions").option("--agent <name>","Filter by agent").option("--source <name>","Filter by executor metadata source (e.g. omni)").option("--limit <n>","Max number of sessions to return (default: 50)").option("--json","Output as JSON").action(async(options)=>{await sessionsListCommand(options)}),sessions2.command("replay <session-id>").description("Replay a session \u2014 interleave content + events").option("--json","Output as JSON").action(async(sessionId,options)=>{await sessionsReplayCommand(sessionId,options)}),sessions2.command("search <query>").description("Full-text search across session content").option("--json","Output as JSON").option("--limit <n>","Max results","20").action(async(query2,options)=>{await sessionsSearchCommand(query2,options)}),sessions2.command("sync").description("Check session backfill progress").action(async()=>{await sessionsSyncStatusCommand()}),sessions2.command("repair-links").description("Diagnose and (with --apply) repair linkable orphan sessions + tool_events attribution").option("--dry-run","Preview only \u2014 never mutates rows (default)").option("--apply","Run the repair transaction").option("--force","Override the candidate-count drift gate and ambiguity gate").option("--json","Output as JSON").action(async(options)=>{await sessionsRepairLinksCommand(options)})}init_state();init_observability_health();init_agent_registry();init_agent_registry();init_derived_signals();init_derived_signals();init_executor_registry();init_should_resume();init_term_format();var ANSI2={reset:"\x1B[0m",dim:"\x1B[2m",bold:"\x1B[1m",red:"\x1B[31m",green:"\x1B[32m",yellow:"\x1B[33m",cyan:"\x1B[36m",magenta:"\x1B[35m"};function colorize(text,color2){if(process.env.NO_COLOR||!process.stdout.isTTY)return text;return`${ANSI2[color2]}${text}${ANSI2.reset}`}async function aggregateAgentDecisions(includeArchived){let agents=await listAgentsForRender({includeArchived}),results=Array(agents.length),cursor=0,cap=Math.min(BOOT_PASS_CONCURRENCY_CAP,Math.max(1,agents.length)),workers=Array.from({length:cap},async()=>{while(cursor<agents.length){let i2=cursor++;if(i2>=agents.length)return;let a=agents[i2],decision=await shouldResume(a.id).catch(()=>({resume:!1,reason:"no_session_id",rehydrate:"lazy"})),name=a.customName??a.role??a.id,sessionPreview=decision.sessionId?decision.sessionId.slice(0,8):null,lastWriteAt=null;if(a.currentExecutorId){let exec3=await getExecutor(a.currentExecutorId).catch(()=>null);lastWriteAt=exec3?.updatedAt??exec3?.startedAt??null}results[i2]={agentId:a.id,name,kind:a.kind??null,decision,sessionPreview,lastWriteAt}}});return await Promise.all(workers),results}async function collectHealthChecks(){let report2=await collectObservabilityHealth();return[{name:"partition",status:report2.partition_health,message:report2.next_rotation_at?`next rotation: ${report2.next_rotation_at}`:void 0},{name:"watchdog",status:report2.watchdog,message:report2.watchdog_detail},{name:"spill journal",status:report2.spill_journal==="pending"?"warn":report2.spill_journal==="unknown"?"unknown":"ok",message:report2.spill_path},{name:"watcher metrics",status:report2.watcher_metrics,message:report2.watcher_metrics==="ok"?"all six recently seen":"one or more meta-events missing"}]}function statusIcon(status){switch(status){case"ok":return colorize("\u2713","green");case"warn":return colorize("!","yellow");case"fail":return colorize("\u2717","red");default:return colorize("?","dim")}}function severityBadge(sev){if(sev==="critical")return colorize("[CRITICAL]","red");if(sev==="warn")return colorize("[WARN]","yellow");return colorize("[INFO]","dim")}function formatAgentLine(line){let kindTag=line.kind==="permanent"?colorize("p","magenta"):colorize("t","cyan"),session=line.sessionPreview?colorize(line.sessionPreview,"dim"):colorize("no-session","yellow"),lastWrite=line.lastWriteAt?formatRelativeTimestamp(line.lastWriteAt):"-",reason=line.decision.reason==="ok"?colorize("resume ready","green"):colorize(line.decision.reason,"yellow");return` [${kindTag}] ${line.name.padEnd(28).slice(0,28)} ${session.padEnd(8)} last:${lastWrite.padEnd(10)} ${reason}`}function renderResumableSection(lines){let resumable=lines.filter((l)=>l.decision.resume);if(resumable.length===0){console.log(colorize(" (no in-flight agents \u2014 every prior anchor is closed or paused)","dim"));return}for(let line of resumable)console.log(formatAgentLine(line))}function renderStuckSection(lines){let stuck=lines.filter((l)=>!l.decision.resume&&l.decision.reason!=="assignment_closed"&&l.decision.reason!=="unknown_agent");if(stuck.length===0)return;console.log(""),console.log(colorize("STUCK / NEEDS ATTENTION","bold")),console.log("-".repeat(60));for(let line of stuck)if(console.log(formatAgentLine(line)),line.decision.reason==="auto_resume_disabled")console.log(colorize(` \u2192 genie agent resume ${line.name}`,"dim"));else if(line.decision.reason==="no_session_id")console.log(colorize(` \u2192 genie agent show ${line.name} # inspect; consider archive`,"dim"))}function renderArchivedSection(lines){let done=lines.filter((l)=>l.decision.reason==="assignment_closed");if(done.length===0)return;console.log(""),console.log(colorize("DONE / ARCHIVED","bold")),console.log("-".repeat(60));for(let line of done)console.log(formatAgentLine(line))}function renderSignalsSection(signals2){if(signals2.length===0){console.log(colorize(" (no active alerts)","dim"));return}for(let sig of signals2){console.log(` ${severityBadge(sig.severity)} ${colorize(sig.type,"bold")} on ${sig.subject}`);let drilldown=SIGNAL_DRILLDOWN[sig.type];if(drilldown)console.log(colorize(` \u2192 ${drilldown}`,"dim"));if(sig.triggeredAt)console.log(colorize(` ${formatRelativeTimestamp(sig.triggeredAt)}`,"dim"))}}function renderHealthSection(checks){for(let check2 of checks){let detail=check2.message?colorize(` ${check2.message}`,"dim"):"";console.log(` ${statusIcon(check2.status)} ${check2.name.padEnd(18)} ${detail}`)}}async function renderDebugSection(){let audit=await auditAgentKind();if(console.log(""),console.log(colorize("DEBUG \u2014 kind audit","bold")),console.log("-".repeat(60)),console.log(` rows scanned: ${audit.total}`),console.log(` drift count : ${audit.drifted.length}`),audit.drifted.length>0)for(let d of audit.drifted.slice(0,10))console.log(colorize(` drift: ${d.id} stored=${d.kind??"null"} expected=${d.expected}`,"yellow"))}async function buildReport(opts){let includeArchived=opts.all===!0,[agents,signals2]=await Promise.all([aggregateAgentDecisions(includeArchived),listActiveDerivedSignals()]),partitionSignal=await detectPartitionMissing().catch(()=>null);if(partitionSignal)await recordDerivedSignal(partitionSignal).catch(()=>{}),signals2.unshift(partitionSignal);let report2={agents,signals:signals2};if(opts.health)report2.health=await collectHealthChecks();return report2}async function statusCommand2(opts={}){let t0=Date.now(),report2=await buildReport(opts);if(opts.json){console.log(JSON.stringify(report2,null,2));return}if(console.log(""),console.log(colorize("IN-FLIGHT \u2014 should resume","bold")),console.log("-".repeat(60)),renderResumableSection(report2.agents),renderStuckSection(report2.agents),opts.all)renderArchivedSection(report2.agents);if(console.log(""),console.log(colorize("ACTIVE SIGNALS","bold")),console.log("-".repeat(60)),renderSignalsSection(report2.signals),report2.health)console.log(""),console.log(colorize("HEALTH","bold")),console.log("-".repeat(60)),renderHealthSection(report2.health);if(opts.debug)await renderDebugSection();console.log(""),console.log(colorize(` rendered in ${Date.now()-t0}ms \u2014 ${report2.agents.length} agents, ${report2.signals.length} signals`,"dim")),console.log("")}init_genie_tokens();init_term_format();var _taskService7;async function getTaskService7(){if(!_taskService7)_taskService7=await Promise.resolve().then(() => (init_task_service(),exports_task_service));return _taskService7}function registerTagCommands(program2){let tag=program2.command("tag").description("Tag management");tag.command("list").description("List all tags").option("--type <typeId>","Filter by task type").option("--json","Output as JSON").action(async(options)=>{try{let tags=await(await getTaskService7()).listTags(options.type);if(options.json){console.log(JSON.stringify(tags,null,2));return}console.log(` ${padRight("ID",20)} ${padRight("NAME",20)} ${padRight("COLOR",10)} TYPE`),console.log(` ${"\u2500".repeat(55)}`);for(let t of tags)console.log(` ${padRight(t.id,20)} ${padRight(t.name,20)} ${padRight(t.color,10)} ${t.typeId??"-"}`);console.log(`
4613
4741
  ${tags.length} tag${tags.length===1?"":"s"}`)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}}),tag.command("create <name>").description("Create a custom tag").option("--color <hex>","Tag color (hex)",palette.textDim).option("--type <typeId>","Associate with a task type").action(async(name,options)=>{try{let ts3=await getTaskService7(),id=name.toLowerCase().replace(/\s+/g,"-"),t=await ts3.createTag({id,name,color:options.color,typeId:options.type});console.log(`Created tag "${t.name}" (${t.id}) with color ${t.color}.`)}catch(error2){console.error(`Error: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}})}init_term_format();var _taskService8;async function getTaskService8(){if(!_taskService8)_taskService8=await Promise.resolve().then(() => (init_task_service(),exports_task_service));return _taskService8}var _boardService2;async function getBoardService2(){if(!_boardService2)_boardService2=await Promise.resolve().then(() => (init_board_service(),exports_board_service));return _boardService2}var _closeMergedService;async function getCloseMergedService(){if(!_closeMergedService)_closeMergedService=await Promise.resolve().then(() => (init_task_close_merged(),exports_task_close_merged));return _closeMergedService}function localActor2(name){return{actorType:"local",actorId:name}}function currentActor3(){let name=process.env.GENIE_AGENT_NAME??"cli";return localActor2(name)}function getRunId(){return process.env.GENIE_RUN_ID??`run-${Date.now()}`}var PRIORITY_COLORS={urgent:"\x1B[31m",high:"\x1B[33m",normal:"\x1B[0m",low:"\x1B[90m"},RESET2="\x1B[0m";async function resolveDefaultBoardId(){try{let{execSync:execSync18}=await import("child_process"),repoRoot=execSync18("git rev-parse --show-toplevel",{encoding:"utf-8"}).trim(),{join:join85}=await import("path"),configPath2=join85(repoRoot,".genie","config.json"),{existsSync:existsSync70,readFileSync:readFileSync45}=await import("fs");if(existsSync70(configPath2)){let config=JSON.parse(readFileSync45(configPath2,"utf-8"));if(config.activeBoard)return config.activeBoard}}catch{}return null}async function handleInvalidStageError(taskId,message){try{let task=await(await getTaskService8()).getTask(taskId);if(!task?.boardId)return;let board=await(await getBoardService2()).getBoard(task.boardId);if(!board)return;let validCols=board.columns.sort((a,b2)=>a.position-b2.position).map((c)=>c.name).join(" \u2192 ");console.error(`Error: ${message}
4614
4742
  Valid columns for board "${board.name}": ${validCols}`),process.exit(1)}catch{}}async function resolveBoardOption(boardName){if(boardName){let board=await(await getBoardService2()).getBoard(boardName);if(!board)console.error(`Error: Board not found: ${boardName}`),process.exit(1);return board.id}return await resolveDefaultBoardId()??void 0}function getProjectName(repoPath){let parts=repoPath.split("/");return parts[parts.length-1]||repoPath}function formatTaskRow(t,showProject,hasExternal){let seq2=showProject?`${getProjectName(t.repoPath)}#${t.seq}`:`#${t.seq}`,title=truncate2(t.title,38),color2=t.status==="archived"?"\x1B[90m":PRIORITY_COLORS[t.priority]??"",due=formatDate(t.dueDate),proj=showProject?`${padRight(getProjectName(t.repoPath),16)} `:"",ext=hasExternal?`${padRight(truncate2(t.externalId??"",25),27)} `:"",statusLabel=t.status==="archived"?"\x1B[90m[archived]\x1B[0m":t.status;return` ${padRight(seq2,showProject?22:6)} ${proj}${padRight(title,40)} ${ext}${padRight(t.stage,12)} ${padRight(statusLabel,12)} ${color2}${padRight(t.priority,10)}${RESET2} ${padRight(due,12)}`}function printTaskList(tasks,showProject=!1){if(tasks.length===0){console.log("No tasks found.");return}let hasExternal=tasks.some((t)=>t.externalId),extCol=hasExternal?`${padRight("EXTERNAL",27)} `:"",projCol=showProject?`${padRight("PROJECT",16)} `:"",header=` ${padRight("#",6)} ${projCol}${padRight("TITLE",40)} ${extCol}${padRight("STAGE",12)} ${padRight("STATUS",12)} ${padRight("PRIORITY",10)} ${padRight("DUE",12)}`,lineLen=(showProject?108:92)+(hasExternal?28:0);console.log(header),console.log(` ${"\u2500".repeat(lineLen)}`);for(let t of tasks)console.log(formatTaskRow(t,showProject,hasExternal));console.log(`
4615
4743
  ${tasks.length} task${tasks.length===1?"":"s"}`)}function printTaskFields(task){console.log(""),console.log(`Task #${task.seq}: ${task.title}`),console.log("\u2500".repeat(60)),console.log(` ID: ${task.id}`),console.log(` Type: ${task.typeId}`),console.log(` Stage: ${task.stage}`),console.log(` Status: ${task.status}`),console.log(` Priority: ${task.priority}`);let optionalFields=[["Description",task.description],["Criteria",task.acceptanceCriteria],["Effort",task.estimatedEffort],["Start",task.startDate?formatDate(task.startDate):null],["Due",task.dueDate?formatDate(task.dueDate):null],["Blocked",task.blockedReason],["Parent",task.parentId],["Release",task.releaseId],["Wish",task.wishFile],["External",task.externalId],["Ext URL",task.externalUrl]];for(let[label,value]of optionalFields)if(value)console.log(` ${padRight(`${label}:`,12)} ${value}`);if(task.checkoutRunId)console.log(` Checkout: ${task.checkoutRunId} (since ${formatTimestamp(task.executionLockedAt)})`);if(console.log(` Created: ${formatTimestamp(task.createdAt)}`),task.startedAt)console.log(` Started: ${formatTimestamp(task.startedAt)}`);if(task.endedAt)console.log(` Ended: ${formatTimestamp(task.endedAt)}`)}async function printTaskRelations(task){let ts3=await getTaskService8(),actors=await ts3.getTaskActors(task.id,task.repoPath);if(actors.length>0){console.log(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automagik/genie",
3
- "version": "4.260501.6",
3
+ "version": "4.260502.1",
4
4
  "description": "Collaborative terminal toolkit for human + AI workflows. NOTE: the npm distribution is being soft-deprecated — the canonical install is `curl -fsSL https://get.automagik.dev/genie | bash` (cosign + SLSA verified). See https://automagik.dev/genie/security/distribution-sovereignty",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genie",
3
- "version": "4.260501.6",
3
+ "version": "4.260502.1",
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.260501.6",
3
+ "version": "4.260502.1",
4
4
  "private": true,
5
5
  "description": "Runtime dependencies for genie bundled CLIs",
6
6
  "type": "module",