Skip to content

fix(runtime): eliminate agent-send TOCTOU that rejects live agents during startup - #9166

Merged
brennanb2025 merged 2 commits into
mainfrom
brennanb2025/bug-7935-triage
Jul 17, 2026
Merged

brennanb2025 merged 2 commits into
mainfrom
brennanb2025/bug-7935-triage

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Jul 17, 2026 •

Copy link
Copy Markdown
Contributor

Landing recommendation

Recommended to land. The change addresses the same startup-time false negative reported in #7935, keeps the existing fail-closed write protections, has a tightly bounded slow path, and passed both focused automation and real Electron validation. PR Checks are currently green.

User problem and root cause

The user could select a live agent from Send notes to an agent and still get “not a recognized agent session” during agent startup; retrying shortly afterward worked. Instrumentation reproduced hundreds of transient no-agent observations during the first seconds of Claude startup.

This was a TOCTOU between independent status reads:

  1. the renderer checked whether the terminal looked like an agent;
  2. the runtime send guard checked again before writing;
  3. those reads could see different foreground-process/title snapshots while the agent was starting or its title was temporarily neutral.

The runtime therefore rejected a live, selected agent even though the terminal identity and permissions were otherwise valid.

Fix

  • Move the transient no-agent handling into the runtime send guard, which owns the final write decision.
  • Recheck only no-agent every 150 ms, with a 1,050 ms wall-clock bound (at most 8 probes), before refusing.
  • Let a guarded runtime arbitrate a renderer preflight no-agent instead of treating that potentially stale snapshot as final.
  • Keep legacy runtime behavior unchanged when guarded send capability is unavailable.

Commits:

  • 462e04e0d — runtime guarded-send retry
  • ae4d42b75 — renderer delegates the transient case to guarded send

Safety / regression analysis

  • No terminal input is written until the guard observes a sendable agent.
  • Exact-PTY targeting, stale-handle rejection, lock/permission checks, and not-writable/unavailable failures remain fail-closed.
  • Errors other than no-agent are not retried or softened.
  • The logic is platform-neutral and uses the existing runtime RPC/status source, so native macOS/Linux/Windows, WSL, SSH, and relay targets retain the same authority and terminal identity checks.
  • No Git/provider behavior or UI shortcut/path behavior changes.

Performance

  • Normal sendable-agent path: no retry delay and no new renderer polling/provider fan-out.
  • Continuously negative path: bounded to 8 lightweight status probes over at most 1.05 seconds, only after an explicit send attempt reports no-agent.
  • No background timer or persistent polling is introduced.

Validation

Automated validation completed locally:

  • 65/65 focused Vitest cases across runtime terminal send guard/send and renderer active-agent note send
  • pnpm typecheck
  • changed-file lint and format checks
  • reliability gates and git diff --check
  • Electron production build
  • GitHub PR Checks: green

Real Electron validation

Ran an isolated Electron instance from this branch with a separate user-data directory and an authenticated Claude Code terminal:

  1. Idle agent: added a real line-level AI review note, selected the visible Idle Claude target, received the success toast, and Claude received the exact file/line/comment payload and replied PR9166_NOTE_RECEIVED.
  2. Working agent / mid-turn: started a real sleep 45 shell command, confirmed Orca showed Claude as Working, then sent another line-level review note to that Working target. Claude replied PR9166_MIDTURN_RECEIVED while explicitly reporting the original sleep was still running; the original command later completed and Claude returned HOLD2_DONE.
  3. The sidebar transitioned Working → Done, the runtime continued to report a live agent, there were 0 Electron console errors, and the agent made no repository changes.

Successful guarded send from the branch diff:

Electron success toast and active-agent state

Idle and mid-turn delivery markers, including completion of the original command:

Claude receives idle and mid-turn review notes

Remaining risk

A naturally occurring neutral-title frame was not deterministically captured during the live Electron run. That exact timing window is covered by focused fake-timer tests for first-probe failure, eventual success, exhaustion, wall-clock bounding, and concurrent sends. Given the bounded scope and the successful idle + mid-turn end-to-end flows, remaining regression risk is low.

Fixes #7935

@coderabbitai

coderabbitai Bot commented Jul 17, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds assertTerminalAgentSendable, which polls terminal agent status within a bounded interval, checks writability, and translates permission, no-agent, and not-writable conditions. Updates terminal.send to use the guard and maps its errors to existing response reasons. Adds fake-timer tests for transient recovery, pre-write rechecking, timeout refusal, and write side effects.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is informative, but it does not include the required template sections or checklist items. Add the required Summary, Screenshots, Testing checklist, AI Review Report, Security Audit, and Notes sections, including cross-platform review confirmation.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes match #7935 by retrying transient no-agent send refusals while preserving the stated safety and fail-closed behavior.
Out of Scope Changes check ✅ Passed The PR appears scoped to the send-guard race fix and its tests, with no obvious unrelated code changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed The title clearly summarizes the main fix: preventing TOCTOU agent-send refusals during startup.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

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.

@brennanb2025
brennanb2025 merged commit b671068 into main Jul 17, 2026
1 check passed
enrick-dev pushed a commit to enrick-dev/orca that referenced this pull request Oct 15, 2026
…ring startup (stablyai#9166)

* fix(runtime): avoid false no-agent send rejection during agent startup

* fix(renderer): let guarded note sends resolve agent status races
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.

[Bug]: Intermittent "not a recognized agent session" when sending notes to a running agent (send-guard TOCTOU race)

1 participant