Skip to content

fix(status-bar): invalidate the CLI session count on kill and restart - #12468

Merged
nwparker merged 3 commits into
mainfrom
fix/status-bar-cli-session-count
Aug 5, 2026
Merged

nwparker merged 3 commits into
mainfrom
fix/status-bar-cli-session-count

Conversation

@nwparker

@nwparker nwparker commented Aug 4, 2026 •

Copy link
Copy Markdown
Contributor

pty:management:killOne / killAll / restart tear sessions down via adapter.shutdown() and broadcast nothing — unlike pty:kill, which ends in sendPtyExitToRenderer. The status-bar count is an event-sourced cache, so killing sessions from Manage Sessions or "Kill all terminals" left the >_ N chip frozen until the popover was opened, which itself triggers a refresh.

Note

The dual-source split described in the issue text was already fixed by merged #9387. This closes a different remaining invalidation gap that produces the same reported symptom.

Fix

Broadcast the teardown so the chip updates without needing the popover opened.

Verification

  • pnpm typecheck clean on this branch
  • This branch's own tests pass; the new cases fail before the change and pass after
  • Split out of the original combined branch; the union of all 12 split branches was diffed back against it to prove nothing was lost

Fixes #8372

Made with Orca 🐋

`pty:management:killOne` / `killAll` / `restart` tear sessions down via `adapter.shutdown()` and broadcast nothing — unlike `pty:kill`, which ends in `sendPtyExitToRenderer`. The status-bar count is an event-sourced cache, so killing sessions from Manage Sessions or "Kill all terminals" left the `>_ N` chip frozen until the popover was opened, which itself triggers a refresh.

> [!NOTE]
> The dual-source split described in the issue text was already fixed by merged #9387. This closes a *different* remaining invalidation gap that produces the same reported symptom.

Broadcast the teardown so the chip updates without needing the popover opened.

Fixes #8372

Co-authored-by: Orca <help@stably.ai>
@coderabbitai

coderabbitai Bot commented Aug 4, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 353166b5-9596-4ab7-82d2-5ecde366a5ed

📥 Commits

Reviewing files that changed from the base of the PR and between c498d2d and b633592.

📒 Files selected for processing (9)
  • config/reliability-gates.jsonc
  • src/renderer/src/components/settings/ManageSessionsSection.tsx
  • src/renderer/src/components/shared/kill-all-terminal-surfaces.test.ts
  • src/renderer/src/components/shared/kill-all-terminal-surfaces.ts
  • src/renderer/src/components/status-bar/ResourceUsageStatusSegment.tsx
  • src/renderer/src/components/status-bar/daemon-session-inventory-invalidation.ts
  • src/renderer/src/components/status-bar/use-resource-session-inventory.test.tsx
  • src/renderer/src/components/status-bar/use-resource-session-inventory.ts
  • tests/e2e/status-bar-session-count-management-kill.spec.ts
💤 Files with no reviewable changes (1)
  • src/renderer/src/components/status-bar/ResourceUsageStatusSegment.tsx

📝 Walkthrough

Walkthrough

Added a listener-based daemon session inventory invalidation mechanism. The session inventory hook refreshes after invalidation when restore readiness is complete and unsubscribes after unmount. Daemon restart, individual session kill, and kill-all operations now emit invalidation events. Kill-all continues cleanup when notification fails. Added unit, reliability, and end-to-end coverage for refresh timing and status-bar session counts.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description explains the bug and fix, but it omits the required screenshots, testing checklist, AI review report, security audit, and notes sections. Add all required template sections, mark completed checks, state whether visual changes exist, and document AI review, security audit, and platform-specific notes.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the status-bar session-count invalidation fix for kill and restart actions.
Linked Issues check ✅ Passed The implementation invalidates the status-bar count after daemon session termination and includes regression coverage for the stale-count scenario in issue [#8372].
Out of Scope Changes check ✅ Passed The configuration, implementation, unit tests, hook tests, and end-to-end regression test all support the session-count invalidation objective.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ 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.

Fails on origin/main, passes on this branch.

Test: drops after Manage Sessions kills a foreign daemon session, popover never opened

Co-authored-by: Orca <help@stably.ai>
@nwparker

nwparker commented Aug 4, 2026

Copy link
Copy Markdown
Contributor Author

Important

Correction to this PR's original description. While building the e2e proof I measured the claim and it was wrong.

I originally wrote that killOne / killAll / restart "broadcast nothing". That is not true for a session this window's own terminal pane is attached to — the daemon fans exit out to every attached client, so pty:exit does reach the renderer and the chip already updates correctly on main. Measured on origin/main:

DIAG exitLog= ["2747ce91-...@@3c92b596"]  victim= 2747ce91-...@@3c92b596  chip= 1   # 2 -> 1, correct on main
PROBE t+1s  chip= 0  daemon= 0  exits= 2                                            # kill-all, correct on main

The gap that does regress is a live daemon session this main process is not attached to — another Orca client, orca serve, or a previous app generation. Manage Sessions lists it, the kill succeeds on both branches, and only the status-bar chip differs. That is the case the proof spec exercises, and it is a real, reachable staleness the fix resolves.

So: the fix is correct and worth landing, but the mechanism in my original description overstated the blast radius. The user-visible symptom in #8372 (stale chip, correct number once the popover is opened) still matches.

Unrelated issue found while stabilising the spec, worth someone's attention: navigating to Settings immediately after a pane split sometimes makes the app kill its own pane PTYs — the daemon log shows the app's client id issuing session-killed ... immediate:true for both its panes ~1s after the management kill. I worked around it in the spec by waiting for a stable pane-identity snapshot before navigating. Not caused by this PR; I have not filed it.

@nwparker

nwparker commented Aug 4, 2026

Copy link
Copy Markdown
Contributor Author

Visual proof

Recorded with --repeat-each=3; the harness refuses to emit a video for a failing run, so this is three consecutive passes.

12468-status-bar-session-count-management-kill.spec.ts.webm

What you are looking at

What a reviewer sees in the recording:

  1. Orca opens on the seeded repo with one terminal pane, then the pane splits vertically into two live terminals.
  2. The status bar (bottom strip) shows the Resource Manager chip: a memory badge, a dot, a terminal glyph, and the number 3 — the two visible panes plus one daemon session owned by another client. Accessible name: "Resource Manager, 3 terminal sessions".
  3. The Settings page opens on the Terminal pane. The "Sessions (3)" table lists all three rows; the third row's id is the foreign session (it has no tab to navigate to).
  4. The reviewer clicks the X on that row; the "Kill this session?" dialog appears naming the session id; the destructive "Kill session" button is clicked. A "Killed session." toast fires and the row disappears from the table (the table refreshes itself on both branches — that part is not the proof).
  5. THE MOMENT THAT MATTERS: with the Resource Manager popover never opened, the status-bar number changes 3 -> 2 on the fix branch. On origin/main that same number stays stuck at 3 for the full 15s poll while the daemon really has only 2 sessions left — that is the recorded failure.

…

It actually captures the bug

Same spec on origin/main:

Run on origin/main (5f9a5b80b37), spec file restored on top:

  ✘  1 [electron-headless] › tests/e2e/status-bar-session-count-management-kill.spec.ts:75:7 › Status bar CLI session count › drops after Manage Sessions kills a foreign daemon session, popover never opened

  1) [electron-headless] › tests/e2e/status-bar-session-count-management-kill.spec.ts:75:7 › Status bar CLI session count › drops after Manage Sessions kills a foreign daemon session, popover never opened

    Error: The status-bar chip stayed at the pre-kill count instead of dropping to 2

    expect(received).toBe(expected) // Object.is equality

    Expected: 2
    Received: 3

    Call Log:
    - Timeout 15000ms exceeded while waiting on the predicate

      172 |
      173 |       // The regression: with no pty:exit and no invalidation the closed chip keeps the stale count.
    > 174 |       await expect
…

Test: drops after Manage Sessions kills a foreign daemon session, popover never opened
Spec: tests/e2e/status-bar-session-count-management-kill.spec.ts (committed to this branch)

Caveats and setup notes from building this proof

Honest limitations and setup facts the lead needs:

  1. Scenario framing. The spec proves the fix for a daemon session owned by a different daemon client. That is the only variant of killOne/killAll/restart I could get to regress on origin/main — see "issues" for the measurements showing the attached-session variants already work on main. If the PR is meant to claim the attached-pane case was broken, that claim is not supported by what I measured; the fix is still correct and this spec proves it fixes a real, reachable staleness.

…

@nwparker
nwparker merged commit 69ca9f9 into main Aug 5, 2026
45 checks passed
enrick-dev pushed a commit to enrick-dev/orca that referenced this pull request Oct 15, 2026
…stablyai#12468)

* fix(status-bar): invalidate the CLI session count on kill and restart

`pty:management:killOne` / `killAll` / `restart` tear sessions down via `adapter.shutdown()` and broadcast nothing — unlike `pty:kill`, which ends in `sendPtyExitToRenderer`. The status-bar count is an event-sourced cache, so killing sessions from Manage Sessions or "Kill all terminals" left the `>_ N` chip frozen until the popover was opened, which itself triggers a refresh.

> [!NOTE]
> The dual-source split described in the issue text was already fixed by merged stablyai#9387. This closes a *different* remaining invalidation gap that produces the same reported symptom.

Broadcast the teardown so the chip updates without needing the popover opened.

Fixes stablyai#8372

Co-authored-by: Orca <help@stably.ai>

* test(e2e): add recordable proof for status-bar-cli-session-count

Fails on origin/main, passes on this branch.

Test: drops after Manage Sessions kills a foreign daemon session, popover never opened

Co-authored-by: Orca <help@stably.ai>

* fix(status-bar): avoid duplicate inventory refresh after kill all

---------

Co-authored-by: Orca <help@stably.ai>
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] outdated running cli count at bottom panel

1 participant