Skip to content

Tab header activity counter misses dispatch agents — only walks grid tree (another grid-vs-dispatch divergence) #104

Closed

Description

@Juliusolsson05

What happened

The active/total counter rendered in each tab's header in `TabBar` (`src/renderer/src/workspace/tile-tree/TabBar.tsx:58-66`) computes its numbers from `collectSessionIds(tab.root)` — i.e. it walks only the visible tile-tree. Detached Dispatch agents owned by the tab are not counted. If a tab has 2 grid panes and 8 dispatched agents active, the counter shows "2 alive / 2 total" instead of the actual 10. The visual cue for "what's happening in this tab" silently lies for every user who works in Dispatch Mode.

This is another instance of the same recurring grid-vs-dispatch divergence captured in #94 — each surface independently decides how to walk "sessions in this tab," and the ones that forget about `detachedDispatchSessionIdsForTab` get it wrong.

Repro

  1. Open a tab.
  2. Spawn 2 grid panes (normal split).
  3. Enter Dispatch Mode and start 5 detached agents in this tab.
  4. Look at the tab's header counter — shows 2 / 2. Should show 7 / 7 (or whatever subset is currently `sessionStatus === 'running'`).

Where

  • `src/renderer/src/workspace/tile-tree/TabBar.tsx:58-66` — the offending derivation:
    ```ts
    const sessionIds = collectSessionIds(tab.root)
    const total = sessionIds.length
    const alive = sessionIds.filter(id => runtimes[id]?.sessionStatus === 'running').length
    ```
  • `src/renderer/src/workspace/dispatch/dispatchSelectors.ts` — exposes `detachedDispatchSessionIdsForTab(state, tab.id)` which is the missing piece.

Output

N/A — UI misreports state, no error.

State

Reproducible any time a tab has detached/dispatch agents. Worse the more Dispatch Mode is used.

Prior PRs that tried to fix symptoms in this exact bug class

Same root pattern surfaced repeatedly across the dispatch-vs-grid split:

Nine PRs (this would be the tenth) all chasing the same shape: a surface that asks "which sessions belong to this tab?" and forgets to ask the detached side. Patching one surface at a time hasn't stopped the next surface from re-tripping.

Sketch

Two paths:

  1. Spot fix (cheap, doesn't address the class): swap `collectSessionIds(tab.root)` for the union with `detachedDispatchSessionIdsForTab(state, tab.id)`. Direct mirror of the PR Include detached Dispatch agents in active-tab transcripts template #83 pattern. Probably ~5 lines.

  2. Right fix (addresses the class): consume the canonical resolver proposed in Commands target grid-only sessions — dispatch agents recurringly fall through every command path #94 (`resolveTabSessions(workspace, tabId): SessionId[]`) once it exists. The TabBar becomes one of the migration call sites for that audit.

Recommend (1) as an immediate patch since the bug is user-visible and the resolver from #94 doesn't exist yet — then (2) folds this site into the resolver migration when #94 lands. Mark this issue as resolved-by-#94 after the spot fix ships, so the consolidation work picks it up cleanly.

Related: #94 (the audit + canonical-resolver work).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions