Skip to content

chore: rolling promotion dev -> main - #1020

Merged
namastex888 merged 14 commits into
mainfrom
dev
Apr 3, 2026
Merged

namastex888 merged 14 commits into
mainfrom
dev

Conversation

@namastex888

@namastex888 namastex888 commented Apr 3, 2026 •

Copy link
Copy Markdown
Contributor

Rolling Promotion PR

Auto-maintained rolling promotion PR from dev to main.

Process:

  • This PR is automatically created and kept open
  • Human reviews and merges when ready
  • Label ready-to-merge added when all checks pass

IMPORTANT: Merge with "Create a merge commit" — NEVER squash.
Squash merging breaks history sync between dev and main,
causing the next rolling PR to show all commits again.

Human approval required for merge to production.

Summary by CodeRabbit

  • Chores

    • Released version 4.260403.3
  • Bug Fixes

    • Prevents nesting conflicts when already inside a tmux session
    • Adds a completion guard to avoid unintended worker respawns after intentional completion
    • Improves stale-spawn reconciliation to mark dead-pane spawns and skip agents with active executors
    • Counts spawning workers toward concurrency limits and applies post-spawn state transitions
    • Ensures updates run from the main branch before pulling
  • Tests

    • New/regression tests for zombie spawns and auto-spawn/completion guard behavior

github-actions Bot and others added 8 commits April 3, 2026 06:21
…1017)

Add completion guard in ensureWorkerAlive() to prevent ghost executor
spawns when stale messages arrive for agents that already finished.
Checks last executor state before attempting auto-spawn — done and
terminated executors are skipped, while error/suspended/first-spawn
cases proceed normally.
…1016)

Add guard in genie.ts no-args entry to detect when already inside the
genie-tui tmux session (via TMUX env var) and exit with a helpful message.
Modify attachTuiSession() to use switch-client instead of attach-session
when already inside any tmux session. Add tests for both code paths.
…ce complexity

Reduces ensureWorkerAlive cognitive complexity from 20 to 16 by
extracting the done/terminated executor check into a standalone helper.
Also fixes unused variable lint warnings in tests.
Prevents mock.module leak that broke spawn/exec imports in other test
files when running the full suite.
bun's mock.module('node:child_process') permanently poisons the shared
module cache, breaking execSync/spawnSync in downstream test files
(wish-state, state). The TUI tmux behavior is covered by the guard in
genie.ts and the switch-client logic is trivial enough to verify manually.
…spawn

Three fixes for agents/executors stuck permanently in 'spawning' state:

1. launchTmuxSpawn: after awaitAgentReadiness(), transition executor to
   'running' and legacy worker to 'idle' — previously nothing triggered
   this transition, leaving all executors stuck in 'spawning'

2. reconcileStaleSpawns: add current_executor_id IS NULL guard so agent
   identity records (from findOrCreateAgent) are not falsely marked as
   errors — they track state through their executor, not the legacy
   state column

3. findOrCreateAgent: explicitly set state=NULL on identity records
   instead of inheriting the 'spawning' default, preventing them from
   being caught by any state-based reconciliation queries
fix: tmux spawn guards — nested cascade, completion guard
@coderabbitai

coderabbitai Bot commented Apr 3, 2026 •

Copy link
Copy Markdown

Caution

Review failed

Pull request was closed or merged during review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 6b6f250f-41b8-4bca-9fc6-ca29f71acbb1

📥 Commits

Reviewing files that changed from the base of the PR and between 16e673b and 7c36d08.

📒 Files selected for processing (1)
  • src/term-commands/brain.ts

📝 Walkthrough

Walkthrough

Bumps package/plugin versions to 4.260403.3, adds a completion guard to avoid auto-spawning workers whose last executor is done or terminated, improves tmux/TUI attach behavior to avoid nested attaches, enhances stale-spawn reconciliation, adjusts concurrency counting for spawning, and adds tests for these flows.

Changes

Cohort / File(s) Summary
Version Bumps
\.claude-plugin/marketplace.json, package.json, plugins/genie/.claude-plugin/plugin.json, plugins/genie/package.json
Bumped package/plugin manifest versions from 4.260403.2 → 4.260403.3.
Executor Completion Guard
src/lib/protocol-router.ts, src/lib/protocol-router.test.ts
Added isExecutorCompleted (uses getCurrentExecutor) and a completion guard in ensureWorkerAlive to skip auto-spawn when last executor is done or terminated. Tests cover done, terminated, error, and no-prior-executor cases.
Tmux / TUI Runtime Guards
src/genie.ts, src/tui/tmux.ts
Entry now checks process.env.TMUX (exits when genie-tui present; warns when switching). attachTuiSession() uses tmux switch-client if already inside tmux, otherwise tmux attach-session.
Agent Registry & Reconciliation
src/lib/agent-registry.ts, src/lib/agent-registry.test.ts
reconcileStaleSpawns() first-pass now filters current_executor_id IS NULL; second-pass checks pane_id liveness and marks dead-pane spawns error with audit reason stale_spawn_dead_pane. findOrCreateAgent() inserts identity agents with state = NULL. Tests updated/added.
Scheduler Concurrency / Zombie Spawns
src/lib/scheduler-daemon.ts, src/lib/__tests__/zombie-spawns.test.ts
attemptAgentResume counts spawning as active toward concurrency cap. Added comprehensive zombie-spawn tests for dead-pane reconciliation and concurrency exclusion behavior.
Tmux Spawn State Transitions
src/term-commands/agents.ts
After awaitAgentReadiness(paneId), mark executor running and legacy worker idle when applicable (errors swallowed).
Misc / CLI runtime
src/genie.ts
Added runtime guards: if TMUX contains genie-tui exit; if TMUX set warn about switching before TUI/serve startup.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant CLI as genie.ts
    participant Router as protocol-router
    participant DB as Executor/DB
    participant Scheduler as scheduler-daemon
    participant Tmux as tmux.ts

    User->>CLI: run genie (no-args)
    CLI->>CLI: check process.env.TMUX
    alt TMUX contains "genie-tui"
        CLI->>CLI: log info and exit
    else TMUX is set
        CLI->>CLI: warn about tmux switch
    end

    CLI->>Router: ensureWorkerAlive(worker)
    Router->>DB: getCurrentExecutor(worker)
    DB-->>Router: executor(state)
    alt state == done or terminated
        Router-->>Router: completion guard -> skip auto-spawn, return null
    else
        Router->>Scheduler: attempt auto-spawn / resume
        Scheduler->>DB: evaluate concurrency (includes spawning)
        alt allowed
            Scheduler->>Tmux: launch/attach TUI or spawn worker
            Tmux->>Tmux: check process.env.TMUX
            alt already in tmux
                Tmux->>Tmux: run "tmux switch-client -t SESSION"
            else
                Tmux->>Tmux: run "tmux attach-session -t SESSION"
            end
        else
            Scheduler-->>Router: skip due to concurrency_cap
        end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 57.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'chore: rolling promotion dev -> main' clearly and concisely describes the changeset as a version bump and feature fixes being promoted from dev to main across multiple files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the version to 4.260403.3 across multiple configuration files and introduces a completion guard in the protocol router to prevent the automatic spawning of agents that have intentionally finished their tasks. It also adds logic to detect and handle nested tmux sessions. Feedback indicates that the implementation of switch-client for TUI session attachment will fail when invoked from a different tmux socket, and it is recommended to revert this change to ensure the TUI opens correctly via nesting.

Comment thread src/tui/tmux.ts
Comment on lines +83 to +88
if (process.env.TMUX) {
// Already inside a tmux session — switch-client avoids nested attach
runTuiTmux(['switch-client', '-t', SESSION_NAME], 'inherit');
} else {
runTuiTmux(['attach-session', '-t', SESSION_NAME], 'inherit');
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The implementation of switch-client here will fail in the most common scenario: when genie is invoked from a standard tmux session on a different socket (e.g., the default socket). Tmux's switch-client only works for clients already attached to the target server. Since genie-tui uses a dedicated socket (-L genie-tui), the command will return a "no current client" error, and the user will not be attached to the TUI.

Additionally, src/genie.ts (line 515) already prevents nesting when the user is on the genie-tui socket. Therefore, when this code is reached while process.env.TMUX is set, it is guaranteed to be a different socket where switch-client is inapplicable. Reverting to attach-session is necessary to ensure the TUI opens correctly (via nesting) when called from another tmux session.

  runTuiTmux(['attach-session', '-t', SESSION_NAME], 'inherit');

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5ac68088f1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// Completion guard: don't auto-spawn agents whose last executor finished
// intentionally. An agent that reached 'done' or 'terminated' shouldn't be
// auto-resurrected by stale messages — explicit dispatch handles re-spawn.
if (await isExecutorCompleted(worker)) return null;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Exempt stopped agents from completion auto-spawn guard

This new guard blocks all auto-spawn when the current executor is terminated, but in this codebase terminated is also the state used when an agent is stopped/suspended for later resume (for example, handleWorkerStop still instructs users to “Send a message to auto-resume” in src/term-commands/agents.ts:1416). Because ensureWorkerAlive now returns early here, message-driven resume via sendMessage no longer reaches template-based respawn for stopped agents, so previously recoverable workers become permanently non-deliverable until manually restarted.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/lib/protocol-router.ts`:
- Around line 69-74: isExecutorCompleted can throw and its call in
ensureWorkerAlive (and the similar call around lines 138-141) may bubble errors
out of sendMessage; wrap calls to isExecutorCompleted (and any direct
getCurrentExecutor usage) in a try/catch inside ensureWorkerAlive (and the other
guard site), catch DB/read errors, log or record the error, and treat the
executor as NOT completed (return false / proceed as alive) so the error does
not propagate; reference the isExecutorCompleted function, ensureWorkerAlive
function, sendMessage call site, and getCurrentExecutor helper when locating the
code to change.

In `@src/tui/tmux.ts`:
- Around line 83-88: The current logic always uses runTuiTmux(['switch-client',
...]) whenever process.env.TMUX is set, which fails if the user is inside a
different tmux server; change this to detect whether the TMUX environment points
at our tmux socket and only use 'switch-client' in that case. Parse
process.env.TMUX (take the socket path before the first comma) and compare it to
your tmux socket identifier (the same symbol used when creating the session,
e.g., the SESSION socket constant or variable used alongside SESSION_NAME); if
they match call runTuiTmux(['switch-client','-t', SESSION_NAME], 'inherit'),
otherwise call runTuiTmux(['attach-session','-t', SESSION_NAME], 'inherit').
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: c125ee0c-8da0-46e9-bf6e-6ee3223b4376

📥 Commits

Reviewing files that changed from the base of the PR and between de1da2c and 5ac6808.

📒 Files selected for processing (8)
  • .claude-plugin/marketplace.json
  • package.json
  • plugins/genie/.claude-plugin/plugin.json
  • plugins/genie/package.json
  • src/genie.ts
  • src/lib/protocol-router.test.ts
  • src/lib/protocol-router.ts
  • src/tui/tmux.ts

Comment on lines +69 to +74
/** Check if a worker's last executor completed intentionally (done/terminated). */
async function isExecutorCompleted(worker: registry.Agent | null): Promise<boolean> {
if (!worker?.currentExecutorId) return false;
const executor = await getCurrentExecutor(worker.id);
return executor != null && (executor.state === 'done' || executor.state === 'terminated');
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Handle executor lookup failures in the completion guard.

isExecutorCompleted() can throw (DB/read error), and it is called before the try/catch in ensureWorkerAlive(). That can now bubble an exception out of sendMessage instead of returning a normal undelivered result.

Suggested fix
 async function isExecutorCompleted(worker: registry.Agent | null): Promise<boolean> {
   if (!worker?.currentExecutorId) return false;
-  const executor = await getCurrentExecutor(worker.id);
-  return executor != null && (executor.state === 'done' || executor.state === 'terminated');
+  try {
+    const executor = await getCurrentExecutor(worker.id);
+    return executor != null && (executor.state === 'done' || executor.state === 'terminated');
+  } catch {
+    // Fail-open: if completion state can't be read, keep prior routing behavior.
+    return false;
+  }
 }

Also applies to: 138-141

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/protocol-router.ts` around lines 69 - 74, isExecutorCompleted can
throw and its call in ensureWorkerAlive (and the similar call around lines
138-141) may bubble errors out of sendMessage; wrap calls to isExecutorCompleted
(and any direct getCurrentExecutor usage) in a try/catch inside
ensureWorkerAlive (and the other guard site), catch DB/read errors, log or
record the error, and treat the executor as NOT completed (return false /
proceed as alive) so the error does not propagate; reference the
isExecutorCompleted function, ensureWorkerAlive function, sendMessage call site,
and getCurrentExecutor helper when locating the code to change.

Comment thread src/tui/tmux.ts
Comment on lines +83 to +88
if (process.env.TMUX) {
// Already inside a tmux session — switch-client avoids nested attach
runTuiTmux(['switch-client', '-t', SESSION_NAME], 'inherit');
} else {
runTuiTmux(['attach-session', '-t', SESSION_NAME], 'inherit');
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

In tmux, does tmux -L switch-client -t work when the current shell is attached to a different tmux server (different socket), or doesswitch-client require a current client on the same server?

💡 Result:

No, tmux -L switch-client -t does not work when the current shell is attached to a different tmux server (different socket). The switch-client command requires a current client attached to the specified server via the -L option. Without an attached client on that server, it fails with "no current client".

Citations:


🏁 Script executed:

# Check the full context of src/tui/tmux.ts to see TMUX_SOCKET, SESSION_NAME, and runTuiTmux
head -150 src/tui/tmux.ts | tail -100

Repository: automagik-dev/genie

Length of output: 3997


🏁 Script executed:

# Find TMUX_SOCKET and SESSION_NAME definitions
rg -n 'TMUX_SOCKET|SESSION_NAME' src/tui/tmux.ts | head -20

Repository: automagik-dev/genie

Length of output: 715


🏁 Script executed:

# Check the runTuiTmux function to confirm it uses -L flag
rg -A 10 'function runTuiTmux|const runTuiTmux' src/tui/tmux.ts

Repository: automagik-dev/genie

Length of output: 721


switch-client should be limited to the genie tmux socket.

Using switch-client for any non-empty TMUX fails when the user is inside a different tmux server. Fall back to attach-session instead.

Suggested fix
 export function attachTuiSession(): void {
-  if (process.env.TMUX) {
+  const inGenieSocket = process.env.TMUX?.includes(TMUX_SOCKET) === true;
+  if (inGenieSocket) {
     // Already inside a tmux session — switch-client avoids nested attach
     runTuiTmux(['switch-client', '-t', SESSION_NAME], 'inherit');
   } else {
     runTuiTmux(['attach-session', '-t', SESSION_NAME], 'inherit');
   }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/tui/tmux.ts` around lines 83 - 88, The current logic always uses
runTuiTmux(['switch-client', ...]) whenever process.env.TMUX is set, which fails
if the user is inside a different tmux server; change this to detect whether the
TMUX environment points at our tmux socket and only use 'switch-client' in that
case. Parse process.env.TMUX (take the socket path before the first comma) and
compare it to your tmux socket identifier (the same symbol used when creating
the session, e.g., the SESSION socket constant or variable used alongside
SESSION_NAME); if they match call runTuiTmux(['switch-client','-t',
SESSION_NAME], 'inherit'), otherwise call runTuiTmux(['attach-session','-t',
SESSION_NAME], 'inherit').

Test and others added 4 commits April 3, 2026 04:31
… from concurrency cap

Bug 1: reconcileStaleSpawns second pass (added in prior commit) now verified
by updating the integration test to expect dead-pane agents ARE cleaned up.

Bug 2: The concurrency cap in attemptAgentResume counted 'spawning' agents
as active, causing zombie spawning agents to block all auto-resume. Adding
'spawning' to the exclusion list fixes this — spawning agents are not yet
consuming compute and should not count toward the cap.
fix(spawn): transition executor state from spawning to running after spawn

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/lib/__tests__/zombie-spawns.test.ts`:
- Around line 119-121: The test uses an unnecessary type assertion: remove the
"as any" from the string literal 'spawning' in the zombieSpawning array creation
so it relies on the existing AgentState type; update both occurrences (the one
creating zombieSpawning and the similar instance around line 156) where
makeWorker({ id: ..., state: 'spawning' as any }) is used to simply pass state:
'spawning' to makeWorker (WorkerInfo).

In `@src/term-commands/agents.ts`:
- Around line 914-921: The code advances executor and worker states regardless
of whether awaitAgentReadiness(paneId) actually succeeded and it swallows any
update errors; change the logic so that
executorRegistry.updateExecutorState(ctx.executorId, 'running') and
registry.update(ctx.workerId, { state: 'idle' }) are only invoked when
awaitAgentReadiness(paneId) returns success (or indicates readiness), and do not
silently ignore failures—handle promise rejections from
executorRegistry.updateExecutorState and registry.update by bubbling/logging the
error instead of using .catch(()=>{}). Use the existing ctx.executorId and
ctx.workerId checks to gate updates and ensure any update failures are logged or
rethrown so state write errors are observable.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: fe0d9053-fadf-4425-a2d5-05a409f19277

📥 Commits

Reviewing files that changed from the base of the PR and between 5ac6808 and 16e673b.

📒 Files selected for processing (5)
  • src/lib/__tests__/zombie-spawns.test.ts
  • src/lib/agent-registry.test.ts
  • src/lib/agent-registry.ts
  • src/lib/scheduler-daemon.ts
  • src/term-commands/agents.ts

Comment on lines +119 to +121
const zombieSpawning: WorkerInfo[] = Array.from({ length: 5 }, (_, i) =>
makeWorker({ id: `zombie-${i}`, state: 'spawning' as any }),
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Unnecessary as any cast.

'spawning' is already a valid AgentState value (per agent-registry.ts line 25). The type assertion is redundant.

♻️ Remove unnecessary cast
-    const zombieSpawning: WorkerInfo[] = Array.from({ length: 5 }, (_, i) =>
-      makeWorker({ id: `zombie-${i}`, state: 'spawning' as any }),
+    const zombieSpawning: WorkerInfo[] = Array.from({ length: 5 }, (_, i) =>
+      makeWorker({ id: `zombie-${i}`, state: 'spawning' }),
     );

Same applies to line 156.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/__tests__/zombie-spawns.test.ts` around lines 119 - 121, The test
uses an unnecessary type assertion: remove the "as any" from the string literal
'spawning' in the zombieSpawning array creation so it relies on the existing
AgentState type; update both occurrences (the one creating zombieSpawning and
the similar instance around line 156) where makeWorker({ id: ..., state:
'spawning' as any }) is used to simply pass state: 'spawning' to makeWorker
(WorkerInfo).

Comment on lines 914 to +921
await awaitAgentReadiness(paneId);

// Transition executor + legacy worker from 'spawning' to 'running'
if (ctx.executorId) {
await executorRegistry.updateExecutorState(ctx.executorId, 'running').catch(() => {});
}
await registry.update(ctx.workerId, { state: 'idle' }).catch(() => {});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Gate 'running'/'idle' transitions on readiness and stop silently swallowing state-write failures.

Line 914 can continue after a readiness timeout, but Lines 918 and 920 still force lifecycle transitions and ignore failures. This can desync executor/worker state and undermine spawn/respawn decisions.

Suggested fix
-async function awaitAgentReadiness(paneId: string): Promise<void> {
-  if (paneId === 'inline') return;
+async function awaitAgentReadiness(paneId: string): Promise<boolean> {
+  if (paneId === 'inline') return true;
   const result = await waitForAgentReady(paneId);
   if (result.ready) {
     console.log(`  ✓ Agent ready (${(result.elapsedMs / 1000).toFixed(1)}s)`);
-  } else {
-    console.log(`  ⚠ Agent readiness timeout (${Math.round(result.elapsedMs / 1000)}s) — proceeding anyway`);
+    return true;
   }
+  console.log(`  ⚠ Agent readiness timeout (${Math.round(result.elapsedMs / 1000)}s) — proceeding anyway`);
+  return false;
 }
@@
-  await awaitAgentReadiness(paneId);
+  const ready = await awaitAgentReadiness(paneId);

-  // Transition executor + legacy worker from 'spawning' to 'running'
-  if (ctx.executorId) {
-    await executorRegistry.updateExecutorState(ctx.executorId, 'running').catch(() => {});
-  }
-  await registry.update(ctx.workerId, { state: 'idle' }).catch(() => {});
+  if (ready) {
+    if (ctx.executorId) {
+      try {
+        await executorRegistry.updateExecutorState(ctx.executorId, 'running');
+      } catch (err) {
+        console.warn(`Warning: failed to update executor "${ctx.executorId}" to running: ${err}`);
+      }
+    }
+    try {
+      await registry.update(ctx.workerId, { state: 'idle' });
+    } catch (err) {
+      console.warn(`Warning: failed to update worker "${ctx.workerId}" to idle: ${err}`);
+    }
+  }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/term-commands/agents.ts` around lines 914 - 921, The code advances
executor and worker states regardless of whether awaitAgentReadiness(paneId)
actually succeeded and it swallows any update errors; change the logic so that
executorRegistry.updateExecutorState(ctx.executorId, 'running') and
registry.update(ctx.workerId, { state: 'idle' }) are only invoked when
awaitAgentReadiness(paneId) returns success (or indicates readiness), and do not
silently ignore failures—handle promise rejections from
executorRegistry.updateExecutorState and registry.update by bubbling/logging the
error instead of using .catch(()=>{}). Use the existing ctx.executorId and
ctx.workerId checks to gate updates and ensure any update failures are logged or
rethrown so state write errors are observable.

Test and others added 2 commits April 3, 2026 05:01
git pull origin main while on dev merges main INTO dev, keeping
the dev-prefix version (1.*). This caused genie brain update to
show wrong version after update (e.g. "Updated: 0.260403.2 →
1.260403.6"). Now explicitly checks out main first.
…-main

fix(brain): checkout main before pulling in brain update
@namastex888
namastex888 merged commit da47fbf into main Apr 3, 2026
8 of 10 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request Apr 16, 2026
@coderabbitai coderabbitai Bot mentioned this pull request May 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant