Skip to content

fix: pr-bug-scan validated finding from #4658#4741

Open
buf0-bot[bot] wants to merge 1 commit into
mainfrom
bot/pr-bug-scan-4658-1780718121
Open

fix: pr-bug-scan validated finding from #4658#4741
buf0-bot[bot] wants to merge 1 commit into
mainfrom
bot/pr-bug-scan-4658-1780718121

Conversation

@buf0-bot
Copy link
Copy Markdown
Contributor

@buf0-bot buf0-bot Bot commented Jun 6, 2026

Automated fix-PR from pr-bug-scan for parent #4658.

Fixer status: FIXED_WITH_CODE_PROOF
Summary: Gate the three unread-clear calls in onTerminalKeyDown so modifier-only/repeat/copy-chord keydowns no longer dismiss sibling-pane attention.
Blocked proof link: src/renderer/src/components/terminal-pane/pty-connection.ts:719 onTerminalKeyDown unconditionally calls deps.clearTerminalTabUnread/clearTerminalPaneUnread/clearWorktreeUnread before any guard
Typecheck: skipped

Proof (from validator)

  • C1 — proof_type: code_analysis
    • trigger: User has a tab with split panes A and B in the same worktree; pane B emits BEL or completion attention while hidden, then user types/presses any key (e.g. holds Shift, presses Cmd+C to copy a selection, autorepeats arrow keys) inside pane A.
    • observable: Tab-level and worktree-level attention dots disappear for sibling pane B as soon as the user types into pane A, even when no real character was sent to any terminal (e.g. Cmd+C with selection, Shift held, Escape pressed).
    • path:
      • src/renderer/src/components/terminal-pane/pty-connection.ts:719 onTerminalKeyDown unconditionally calls deps.clearTerminalTabUnread(deps.tabId), deps.clearTerminalPaneUnread(cacheKey), deps.clearWorktreeUnread(deps.worktreeId) before any guard
      • src/renderer/src/components/terminal-pane/pty-connection.ts:744 listener is registered on pane.terminal.element with capture:true so every key — including modifier-only, repeat, copy, plain Escape — reaches the handler
      • src/renderer/src/components/terminal-pane/pty-connection.ts:1309 onData (post-diff) intentionally no longer clears unread, so this is the only clear path for keyboard interaction
  • C2 — proof_type: code_analysis
    • trigger: Settings: experimentalTerminalAttention=true, notifications.agentTaskComplete=false, notifications.terminalBell=true. An agent emits BEL during the same burst as its working→idle transition (typical Claude/Codex completion).
    • observable: No terminal-bell OS notification is delivered for the BEL that the user explicitly enabled; only the silent attention dot is set.
    • path:
      • src/renderer/src/components/terminal-pane/pty-connection.ts onBell sets pendingTerminalBellNotification=true and schedules a bell OS notification because hasPendingAgentTaskCompleteNotification() short-circuits on isAgentTaskCompleteNotificationEnabled()=false
      • src/renderer/src/components/terminal-pane/pty-connection.ts:1068 scheduleAgentTaskCompleteNotification now runs because syncAgentTaskCompleteTrackingEnabled() returns true (attention is on)
      • src/renderer/src/components/terminal-pane/pty-connection.ts:1090-1099 dispatch() sets pendingTerminalBellNotification=false and calls clearTerminalBellNotificationTimer() before invoking deps.dispatchNotification with suppressOsNotification:true
      • src/renderer/src/components/terminal-pane/use-notification-dispatch.ts:286-288 dispatchTerminalNotification returns early on suppressOsNotification before window.api.notifications.dispatch — no OS notification fires

Generated by pr-bug-scan (proof-machine architecture). Human approval required before merge.

Gate the three unread-clear calls in onTerminalKeyDown so modifier-only/repeat/copy-chord keydowns no longer dismiss sibling-pane attention.
Copy link
Copy Markdown
Contributor

@pullfrog pullfrog Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ No critical issues — minor test-coverage observation inline.

Reviewed changes — gates onTerminalKeyDown unread-clearing so that modifier-only key presses, autorepeat, and copy chords (Cmd/Ctrl+C with active selection) no longer dismiss sibling-pane attention dots. This addresses the validated finding from #4658 where typing into pane A would prematurely clear attention for pane B.

  • Gate unread clearing in onTerminalKeyDown — moves the three clear*Unread calls after the escape/Ctrl-C intent checks and adds two early-return guards: one for modifier-only/repeat keydowns, one for copy chords with an active selection.

Pullfrog  | Fix all ➔Fix 👍s ➔View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

// "user is here" signal. Modifier-only presses, autorepeat, and Cmd/Ctrl+C
// copy chords with an active selection must not dismiss attention on a
// sibling pane before the user has seen it.
if (
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ The modifier-only/repeat guard and copy-chord guard added here have no test coverage. The existing test at pty-connection.test.ts:4860 (clears tab and worktree unread on real keydown) only exercises the happy path with key='a', no modifiers, repeat=false. Consider adding tests for:

  • Modifier-only presses (key='Shift', key='Alt', key='Control', key='Meta') — assert unread is not cleared
  • Repeat events (key='a', repeat=true) — assert unread is not cleared
  • Copy chord with selection (key='c', ctrlKey=true or metaKey=true, hasSelection()=true) — assert unread is not cleared
Technical details
# Missing test coverage for `onTerminalKeyDown` guard conditions

## Affected sites
- `src/renderer/src/components/terminal-pane/pty-connection.ts:736-752` — new modifier-only/repeat guard and copy-chord guard
- `src/renderer/src/components/terminal-pane/pty-connection.test.ts:4860-4884` — existing happy-path test, no guard-coverage tests

## Required outcome
- Each guard condition path (modifier-only, repeat, copy-chord) should have a dedicated test asserting that `clearTerminalTabUnread`, `clearTerminalPaneUnread`, and `clearWorktreeUnread` are NOT called.

## Suggested approach
- Dispatch `keydown` events with the guard-triggering properties (e.g. `key='Shift'`, `repeat=true`, or `key='c'` + `ctrlKey=true` + mock `hasSelection()`) and assert the three clear functions were not called, mirroring the pattern of the existing test at line 4860.

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.

0 participants