Repository navigation
[Bug]: Send-notes offer path and terminal.agentStatus pre-check derive agent aliveness independently (structural offer-then-refuse) #26568
Description
Operating system
Windows (original report); the gap itself is platform-independent
Orca version
v1.4.217 (original report); verified against main @ 7c50009ca4946cf7384495f542d0b5856308b70c
Details
Short summary: the "Send notes to" target list and the send pre-check answer "is an agent alive in this pane?" with two independent derivations. When they disagree, a target is offered and then refused — the structural remainder of #24286 that would remain even if the proposed spinner-title fix #25513 lands. #25513 is open, not merged: main @ 7c50009c still accepts a lone quarter-circle title in detectAgentSendTitleStatus, so the guard exists only inside that PR — and this gap is independent of it, because the mismatch below lives in the status-store lane and the runtime verdict, neither of which goes through the title lane.
The two derivations (file:line on main @ 7c50009c):
- Offer:
deriveTerminalAgentSendTargets(src/renderer/src/lib/running-agent-targets.ts:84-162) iterates the renderer's hook store (agentStatusByPaneKey, 30-minute freshness viapane-agent-evidence.ts) plus a live-title override. It never consultsisRunningAgent. - Refusal:
src/renderer/src/lib/active-agent-terminal-send-readiness.ts:32-44→terminal.agentStatus→!isRunningAgent→'no-agent'. isRunningAgentderivation:terminal-query-methods.ts:104-110→runtime-terminal-agent-status-query.ts:69-139(permission-title / blocked-text / hook-status branch / title-status branch / presence-engine fallback). Hook rows are stale after 30 minutes (AGENT_STATUS_STALE_AFTER_MS,src/shared/agent-status-freshness.ts).
Nothing keeps the two sides consistent: any pane whose renderer-store evidence is fresher than what the main-process derivation accepts can be offered and then refused with no lane that reconciles them.
Historical reproduction (v1.4.217 — not evidence against current main): Viy1204's Antigravity case in #24286 (see issuecomment-6051319515):
- pane titled
C:\Program Files\PowerShell\7\pwsh.exe,agentIdentity: "antigravity"from the foreground-process check (detectCmd: 'agy'); - hook status (
agent-hooks/last-status.json) never written for a fresh pane, one staleStop(8 days old) for the original pane; - the pane shows up in the send menu, then the pre-check refuses with
no-agent.
Caveats from the reporter, kept intact: measured on v1.4.217, which predates #24222 / #24348 (screen-readiness for Antigravity; first release containing them is v1.4.220), so the tui-idle timeout half of his report is the already-fixed #24486 symptom and needs a re-test on ≥ v1.4.220 before it counts against current code. He also could not read isRunningAgent directly. And on current main a pane without a fresh explicit status falls back to isTerminalRunningAgent() → the presence engine, which recognizes the foreground process via recognizeAgentProcess (detectCmd: 'agy', shared/tui-agent-config.ts) — so agentIdentity: "antigravity" observed on 1.4.217 does not imply that current terminal.agentStatus also returns false. The offer-then-refuse pair must be re-reproduced on a current build before it counts as a current bug; the structural gap above rests on the code paths alone.
Open questions (design, not yet decided):
- Should offer eligibility and the send pre-check consult one shared derivation of "agent aliveness here", instead of a renderer copy that can drift from the runtime verdict?
- For Antigravity on Windows specifically: is the hook channel expected to ever write fresh rows for
agy? If not, both sides must fall back to process/screen evidence — related to [Bug]: Windows: Antigravity (agy) sessions missing from sidebar — orca-status bundle wiped from ~/.gemini/config/hooks.json and never reinstalled #17672 (hooks.json wiped and never reinstalled on Windows).
Related: #24286 (original; Refs only — its spinner-title lane is addressed by #25513, open and unmerged), #24486 (tui-idle screen read, fixed in v1.4.220), #17672 (Windows hooks installation).
Activity
bashrusakh commentedon Oct 8, 2026
Proposed fix direction: make Send Notes eligibility runtime-authoritative
I would fix this at the Send Notes authority boundary, rather than by adding another renderer-side heuristic or by attempting a repo-wide unification of all agent-presence semantics.
The core problem is not a single missing condition. Today, two independent paths answer effectively the same product question:
As long as those remain independent derivations, they can drift. Fixing individual mismatches in the renderer only moves the divergence point.
Proposed authority model
For Send Notes, the runtime should be the single authority for:
The renderer may still perform candidate discovery, but it should not independently make the final
eligibledecision.Conceptually:
The final send-time guard should remain in place and call the same runtime authority again, because terminal state may change between opening the menu and clicking Send.
Suggested separation of responsibilities
deriveTerminalAgentSendTargetsshould answer:It should not be the final authority for:
The latter should come from the runtime.
That would turn the current flow from:
into:
Why not copy more runtime checks into the renderer?
That would preserve the underlying problem.
The runtime presence decision can depend on evidence such as:
The renderer does not necessarily have all of that evidence, and duplicating the runtime rules would create another implementation that must remain synchronized indefinitely.
A local patch such as adding the current shell-title rejection to the renderer may fix one reproduction while leaving the same structural failure mode available through another evidence combination.
Why not introduce one global
isAgentAlive()abstraction for all Orca consumers?That seems broader than necessary for this issue.
Different consumers legitimately ask different questions:
Those do not necessarily need identical evidence or policy.
So I would avoid turning #26568 into a global agent-state refactor. The narrower invariant needed here is:
Concrete invariant
After the fix, this should not be possible purely because the renderer and runtime interpreted agent presence differently:
A target may still become invalid between discovery and send because state changed, which is why the final guard remains necessary. But the menu and the send guard should not disagree because they use different definitions of agent presence.
Scope
This is intentionally between two extremes:
The proposed scope is:
That removes the structural offer-then-refuse class without weakening the existing fail-closed send guard.
AmethystLiang commentedon Oct 8, 2026
Thanks for reporting. Looking into it