Skip to content

notifications: pane-scoped active-tab suppression — split-pane agents go unnoticed #549

@Axelj00

Description

@Axelj00

Problem

The active-tab suppression check is at tab granularity, not pane granularity. If you split a tab into 4 panes — each running a different agent — and you're focused on pane A, pane B's OSC 9;2 produces no system notification, because activeTabId === tab.id.

You're not looking at pane B. The whole point of multi-pane is independent agents. This breaks the "Claude is asking me a question" guarantee for everyone running >1 pane per tab.

Current code

src/terminal-manager.ts line ~775 (post-#547):

tab.onOscNotification = (text) => {
  if (tab.muted) return;
  if (this.activeTabId === tab.id && !document.hidden) return;  // ← too coarse
  this.notifications.notifyAgentAttention(text, tab.title, tab.id);
};

The signal needs to be: "is the user currently looking at the pane that emitted the OSC?" not "is the user currently on this tab?"

Proposal

Plumb the source pane through the OSC notification path. Tab.handleOscNotification already receives the originating Pane (src/tab.ts:195). Forward it through onOscNotification instead of dropping it:

// Tab
onOscNotification: ((text: string, pane: Pane) => void) | null = null;

private handleOscNotification(pane: Pane, text: string) {
  if (this.muted) return;
  const showGrace = Date.now() - this.lastShownAt < 3000;
  if (!this.isVisible && !this.transitioning && !showGrace) {
    this.state.needsAttention = true;
    this.onStateChange?.();
  }
  this.onOscNotification?.(text, pane);
}
// TerminalManager
tab.onOscNotification = (text, pane) => {
  if (tab.muted) return;
  const isFocusedPaneOnActiveTab =
    this.activeTabId === tab.id && tab.getFocusedPane() === pane && !document.hidden;
  if (isFocusedPaneOnActiveTab) return;
  this.notifications.notifyAgentAttention(text, tab.title, tab.id);
};

Acceptance

  • 4-pane tab, you're looking at pane A. Pane B OSCs → banner fires.
  • 4-pane tab, you're looking at pane A. Pane A OSCs → no banner.
  • 1-pane tab (the common case) → behavior unchanged.

Files

File Change
src/tab.ts onOscNotification signature gains a Pane argument
src/pane.ts (no change — already passes this up via existing onOscNotification
src/terminal-manager.ts Check tab.getFocusedPane() === pane instead of tab equality

Notes

  • Today's behavior is correct for the 1-pane case, which is most users today. This bug bites people running multiple agents per tab via splits.
  • The "click → tab" flow doesn't change. Click still resolves to a tab, not a pane (focusing the right pane within the tab is a future enhancement).

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent-uxAI agent experience and visibilitybugSomething isn't workinguxUser experience and interaction quality

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions