Skip to content

feat: import remaining T3Code immediate-wave improvements - #101

Merged
Jay1 merged 19 commits into
mainfrom
feature/t3code-immediate-wave
Jul 30, 2026
Merged

feat: import remaining T3Code immediate-wave improvements#101
Jay1 merged 19 commits into
mainfrom
feature/t3code-immediate-wave

Conversation

@Jay1

@Jay1 Jay1 commented Jul 29, 2026

Copy link
Copy Markdown
Owner

Summary

Imports the remaining JCode-native improvements from the T3Code immediate-wave branch across web UX, desktop UX, server hardening, and model metadata.

The current main branch was merged into this feature branch with the normal merge commit fcdaeba9fe923a52b9d8cf6f50f96da81b4974da. No rebase, amend, force push, or other history rewrite was used. The original import covered exactly 59 files; review follow-ups bring the final PR scope to exactly 64 files (5,072 additions and 170 deletions) across 19 total commits, 18 of them non-merge.

Changes

Web UX

Desktop UX

Server hardening

Model metadata

Review follow-ups

Eight linear, non-rewriting commits address all 12 original CodeRabbit themes and the subsequent review findings:

Addressed themes:

  1. Lazily construct each Claude subscription probe with a fresh abort controller and query.
  2. Exercise closed-state PageDown behavior through a still-connected branch input.
  3. Synchronize variable-height page navigation with the Base UI combobox highlight and active descendant.
  4. Pluralize additions and deletions independently with locale-aware rules.
  5. Give compact diff statistics a naming-capable role="img" accessibility contract.
  6. Poll computed message-action opacity instead of relying on a fixed transition delay.
  7. Extract provider-model formatting/capability helpers into a tested logic module.
  8. Cache fixed-provider metadata outside the model-option loop.
  9. Link exact diff-stat text through hidden aria-describedby descriptions in both consumers.
  10. Cap recursive markdown-list recovery and preserve pathological remainder as literal code.
  11. Replace opaque status-motion hashes with targeted structural assertions.
  12. Apply minimum-provider-version gating generically with model-specific display names.

Final follow-up findings:

  • Synchronize the deferred branch filter before deriving a live-viewport, mixed-row-height PageDown oracle.
  • Keep English addition/deletion plurals count-based while retaining locale-aware number formatting.
  • Move the live Base UI highlight on End so aria-activedescendant and an immediate Enter select the final branch.
  • Derive provider update guidance from the provider display name instead of hardcoding Claude Code.

Final branch-navigation refactor:

  • Extract page-target calculation into a pure colocated logic module with focused PageUp, PageDown, End, boundary, and viewport-budget tests.
  • Centralize the 28 px, 44 px, 48 px, and 224 px row/viewport contracts and keep rendered height classes aligned with the virtualizer.
  • Consolidate browser-test keyboard dispatch through one parameterized helper while preserving event behavior.

Verification

Original import verification

  • Focused suites: 75 test files, 749 tests passed across server, desktop, contracts, shared, web unit, and web browser coverage.
  • Repository gates: formatting checked across 1,446 files; lint completed with zero errors; typecheck passed 9/9 packages; root tests passed 4,637 tests with 9 skipped; full browser tests passed 341/341.
  • Packaging and release checks: desktop build passed 6/6 tasks; AppImage, preload markers, release smoke, and release notes checks passed.
  • Visual QA: 48 captured states inspected across 375 px, 768 px, and 1280 px viewports, including keyboard focus, reduced motion, diff tree, branch selector, message actions, model traits, and macOS inset coverage.

Review follow-up verification

  • Frozen install passed.
  • Focused import suites passed: server 96/96, desktop 114/114, contracts 171/171, shared 187/187, web unit 76/76, and browser 114/114.
  • Review-delta suites passed: web unit 111/111, browser 35/35, server probe 6/6, and shared compatibility 21/21.
  • Repository gates passed: formatting across 1,448 files; lint with zero errors (581 pre-existing warnings); typecheck 9/9; authoritative root rerun 12/12 tasks with 387 files and 4,655 tests passed, 3 files and 9 tests skipped; full browser 23/23 files and 342/342 tests.
  • Desktop and release gates passed: exact fresh desktop build 6/6, AppImage, preload verification, release smoke, and release notes.
  • Visual QA passed: 1/1 deterministic harness with 48 captures at 375 px, 768 px, and 1280 px, followed by two independent high-confidence reviews.
  • One unchanged process-observation test was isolated green 10/10; the authoritative full rerun also completed green.

Summary by CodeRabbit

  • New Features
    • Added Claude Sonnet 5 model support with detailed capabilities, effort options, and provider-version compatibility gating.
    • Introduced desktop fullscreen state support and more consistent context-menu positioning based on zoom.
    • Improved macOS Electron title-bar/sidebar spacing via traffic-light inset handling.
    • Enhanced chat diff statistics with accessible tooltips and screen-reader descriptions.
  • Bug Fixes
    • Standardized message action visibility/hover/focus behavior for better accessibility.
    • Updated “running”/status motion to a unified persistent status pulse with reduced-motion support.
  • Documentation
    • Refreshed UI motion and chat transcript design guidance for consistent status/action patterns.

Final follow-up verification

  • Focused suites passed: shared compatibility 22/22, diff-label unit coverage 40/40, and branch/model browser coverage 51/51.
  • Repository gates passed: typecheck 9/9 and the authoritative root suite with 2,272 tests.
  • Full browser verification passed 23/23 files and 342/342 tests.
  • Fresh desktop build and package verification passed, including AppImage and preload checks.
  • Visual QA passed across 48 captures at 375 px, 768 px, and 1280 px.

Branch-navigation refactor verification

  • Focused suites passed: branch-navigation logic 19/19 and selector browser coverage 16/16.
  • Repeat verification passed across 10/10 consecutive runs, with 363,375 zero-delta navigation cases.
  • Repository gates passed: typecheck 9/9 and the authoritative root suite with 2,272 tests.
  • Full browser verification passed 23/23 files and 342/342 tests.
  • Fresh desktop build and package verification passed, including AppImage and preload checks.
  • Visual QA passed across 48 captures at 375 px, 768 px, and 1280 px.

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The pull request adds desktop fullscreen and context-menu infrastructure, literal Git path handling, isolated Claude subscription probing, Claude Sonnet 5 metadata and compatibility gating, web accessibility and rendering improvements, macOS traffic-light inset handling, Markdown recovery, and unified status-motion behavior.

Changes

Desktop runtime bridges

Layer / File(s) Summary
Zoom-aware context-menu popup flow
apps/desktop/src/contextMenuPopup.ts, apps/desktop/src/menuCoordinates.ts, apps/desktop/src/main.ts, apps/desktop/src/*Popup.test.ts
Context-menu ownership and zoom-adjusted coordinate handling are extracted into typed helpers and covered by fallback and invalid-input tests.
Fullscreen IPC lifecycle
apps/desktop/src/fullscreenWindow.ts, apps/desktop/src/fullscreenBridge.ts, apps/desktop/src/main.ts, apps/desktop/src/preload.ts, apps/web/src/desktopFullscreen.ts
Fullscreen state is queried from sender windows, broadcast through IPC, exposed to the renderer, synchronized with React subscribers, and cleaned up on window closure.

Server staging and provider probing

Layer / File(s) Summary
Literal Git paths and Claude subscription probing
apps/server/src/git/Layers/GitCore.ts, apps/server/src/provider/*
Selected Git paths use literal pathspec interpretation, while Claude subscription checks use an isolated environment, abortable prompt, timeout, and soft-failure behavior.

Claude Sonnet 5 model support

Layer / File(s) Summary
Sonnet 5 metadata and compatibility gating
packages/contracts/src/model.ts, packages/shared/src/modelCompatibility.ts, apps/web/src/components/chat/ProviderModelPicker.tsx, apps/web/src/appSettings.ts
Sonnet 5 capabilities, aliases, provider-version compatibility rules, picker descriptions, disabled states, and settings examples are added.

Web interaction and rendering

Layer / File(s) Summary
Branch picker navigation and Markdown recovery
apps/web/src/components/BranchToolbarBranchSelector*, apps/web/src/markdown-list-indentation*, apps/web/src/components/ChatMarkdown.tsx
Virtualized branch lists gain measured row navigation and reset handling, and Markdown rendering recovers eligible over-indented list content.
Compact and accessible diff statistics
apps/web/src/components/chat/DiffStatLabel*, apps/web/src/components/DiffPanel.tsx, apps/web/src/components/chat/MessagesTimeline*
Diff statistics gain compact formatting, exact accessible descriptions, tooltips, fixed grid layout, and consumer accessibility wiring.
Mac inset and status motion integration
apps/web/src/macTrafficLightInset*, apps/web/src/components/ChatView.tsx, apps/web/src/components/Sidebar.tsx, apps/web/src/index.css, apps/web/src/components/StatusMotion.browser.tsx
Mac traffic-light offsets are centralized and fullscreen-aware, while message actions and persistent status indicators use shared CSS patterns with reduced-motion behavior.

Estimated code review effort: 5 (Critical) | ~120 minutes

Suggested labels: vouch:trusted, size:XL

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 2.60% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title accurately summarizes the PR's main theme: importing the remaining T3Code immediate-wave improvements.
Description check ✅ Passed The description covers Summary, Changes, and Verification in detail, but omits the Why, UI Changes, and Reviewer Notes sections from the template.
✨ Finishing Touches 💡 1
📝 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.

@github-actions github-actions Bot added size:XXL vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. labels Jul 29, 2026
@Jay1
Jay1 marked this pull request as ready for review July 30, 2026 00:00

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 12

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/server/src/provider/claudeSubscriptionProbe.ts`:
- Around line 142-183: Wrap the probe construction in Effect.suspend so
dependencies.createAbortController and buildClaudeSubscriptionProbeQuery execute
only when the Effect runs, not when probeClaudeSubscription is called. Keep the
existing tryPromise, ensuring, timeout, result, and mapping behavior inside the
suspended effect so each retry receives a fresh AbortController and query setup.

In `@apps/web/src/components/BranchToolbarBranchSelector.browser.tsx`:
- Around line 238-242: Update the PageDown test around handleBranchInputKeyDown
so its closed-state assertion uses a still-connected input, such as reopening
the selector and dispatching PageDown on the fresh input while the list remains
below the virtualization threshold; otherwise remove the “and after close” claim
from the test name. Ensure the assertion exercises the !isBranchMenuOpen guard
rather than dispatching on a detached searchInput.

In `@apps/web/src/components/BranchToolbarBranchSelector.tsx`:
- Around line 763-790: Update handleBranchInputKeyDown so PageDown changes the
Base UI combobox’s highlighted item, not only highlightedBranchIndexRef, and
assert that aria-activedescendant matches the resulting target. Keep the
virtualizer viewport aligned after the combobox highlight callback runs. Replace
the fixed 28px page-size calculation with the virtualizer’s actual estimated row
sizes, including the 44px PR checkout and 48px current-branch-with-summary
variants.

In `@apps/web/src/components/chat/DiffStatLabel.logic.ts`:
- Around line 28-35: Update formatDiffStatAccessibleLabel to pluralize
“addition” and “deletion” independently based on their numeric counts, using
Intl.PluralRules with the provided locales where appropriate. Preserve
formatExactDiffCount for localized numbers and ensure singular counts produce
“addition”/“deletion” while other counts retain plural forms.

In `@apps/web/src/components/chat/DiffStatLabel.tsx`:
- Around line 16-65: The aria-label on the wrapper span in DiffStatLabel must
use a naming-capable accessibility pattern. Add role="img" to the aria-labeled
wrapper if it represents the compact diff stat as an image alternative, or move
exactLabel to a visually hidden label and mark the glyph-only wrapper
aria-hidden; preserve the existing visual rendering.

In `@apps/web/src/components/chat/MessagesTimeline.browser.tsx`:
- Around line 95-99: Replace the fixed-delay implementation of
waitForMessageActionTransition with a vi.waitFor polling loop that checks the
relevant element’s computed opacity until the CSS transition completes. Remove
the MESSAGE_ACTION_TRANSITION_MS timeout dependency and preserve the function’s
Promise<void> contract.

In `@apps/web/src/components/chat/ProviderModelPicker.tsx`:
- Around line 193-221: Extract the pure helpers formatModelTokenCount and
resolveModelCapabilityDescription from ProviderModelPicker.tsx into a colocated
.logic.ts module, preserving their current behavior and exports needed by the
component. Update ProviderModelPicker to import them, and add direct logic tests
covering formatting boundaries and non-round token counts using the repository’s
existing *.logic.test.ts pattern.
- Around line 439-475: In renderModelRadioGroup, hoist the props.providers
lookup for the fixed provider into a single variable before the model-option
loop, then pass that cached version to each resolveModelCompatibility call.
Remove the repeated props.providers?.find expression from the per-option
rendering while preserving the existing null fallback.

In `@apps/web/src/components/DiffPanel.tsx`:
- Line 937: Add a visually hidden DOM element containing the diff-stat
description, then associate it with both aria-description call sites in
apps/web/src/components/DiffPanel.tsx#937 and
apps/web/src/components/chat/MessagesTimeline.tsx#2062 using the shared or
corresponding description ID. Ensure the exact additions/deletions text is
exposed through the hidden description and remains immediately available to
assistive technology on focus.

In `@apps/web/src/markdown-list-indentation.ts`:
- Around line 132-186: Add a fixed recursion-depth cap to
attachListItemIndentationNormalizer, threading the current depth through visit
and blocksFromIndentedCode; when the cap is exceeded, stop recovery and preserve
the remaining node as literal code. In
apps/web/src/markdown-list-indentation.test.tsx lines 1-158, add a regression
test with at least 50 nested over-indented list levels that verifies parsing
terminates safely at the cap.

In `@apps/web/src/statusMotion.structure.test.tsx`:
- Around line 82-107: Replace the SHA-256 assertions in the test case “preserves
finite spinner, skeleton, shimmer, and ultrathink exclusions byte-for-byte” with
targeted structural or occurrence-based assertions for spinnerSource,
sidebarSkeleton, generatedImageShimmer, and ultrathinkMotion. Assert the
specific motion patterns and exclusions those regions must retain, following the
diagnostic regex-style checks already used elsewhere in the file, and remove the
brittle hash expectations.

In `@packages/shared/src/modelCompatibility.ts`:
- Around line 79-96: Update resolveModelCompatibility to enforce version gating
whenever getModelCapabilities returns a defined minimumProviderVersion, without
checking for the hardcoded "claude-sonnet-5" model slug. Build the rejection
reason from the resolved model’s display name or another model-specific name
supplied through the existing capabilities/input plumbing, so future models
receive accurate messages while preserving selectable behavior when versions are
missing, invalid, or sufficient.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 554460fe-8f70-4e21-ba67-b03cbae134ca

📥 Commits

Reviewing files that changed from the base of the PR and between 36713a8 and fcdaeba.

📒 Files selected for processing (59)
  • DESIGN.md
  • apps/desktop/src/contextMenuPopup.test.ts
  • apps/desktop/src/contextMenuPopup.ts
  • apps/desktop/src/fullscreenBridge.test.ts
  • apps/desktop/src/fullscreenBridge.ts
  • apps/desktop/src/fullscreenWindow.test.ts
  • apps/desktop/src/fullscreenWindow.ts
  • apps/desktop/src/main.ts
  • apps/desktop/src/menuCoordinates.test.ts
  • apps/desktop/src/menuCoordinates.ts
  • apps/desktop/src/preload.ts
  • apps/server/src/git/Layers/GitCore.test.ts
  • apps/server/src/git/Layers/GitCore.ts
  • apps/server/src/provider/Layers/ProviderHealth.ts
  • apps/server/src/provider/claudeSubscriptionProbe.test.ts
  • apps/server/src/provider/claudeSubscriptionProbe.ts
  • apps/web/src/appSettings.test.ts
  • apps/web/src/appSettings.ts
  • apps/web/src/components/BranchToolbar.structure.test.ts
  • apps/web/src/components/BranchToolbarBranchSelector.browser.tsx
  • apps/web/src/components/BranchToolbarBranchSelector.tsx
  • apps/web/src/components/ChatMarkdown.tsx
  • apps/web/src/components/ChatView.tsx
  • apps/web/src/components/DiffPanel.tsx
  • apps/web/src/components/Sidebar.tsx
  • apps/web/src/components/StatusMotion.browser.tsx
  • apps/web/src/components/chat/ChangedFilesTree.browser.tsx
  • apps/web/src/components/chat/DiffStatLabel.browser.tsx
  • apps/web/src/components/chat/DiffStatLabel.consumers.test.ts
  • apps/web/src/components/chat/DiffStatLabel.logic.test.ts
  • apps/web/src/components/chat/DiffStatLabel.logic.ts
  • apps/web/src/components/chat/DiffStatLabel.tsx
  • apps/web/src/components/chat/DiffStatLabel.visual.browser.tsx
  • apps/web/src/components/chat/MessagesTimeline.browser.tsx
  • apps/web/src/components/chat/MessagesTimeline.tsx
  • apps/web/src/components/chat/ProviderModelPicker.browser.tsx
  • apps/web/src/components/chat/ProviderModelPicker.tsx
  • apps/web/src/components/chat/TraitsPicker.browser.tsx
  • apps/web/src/components/macTrafficLightInset.browser.tsx
  • apps/web/src/components/terminal/TerminalActivityIndicator.tsx
  • apps/web/src/components/ui/sidebar.tsx
  • apps/web/src/desktopFullscreen.test.ts
  • apps/web/src/desktopFullscreen.ts
  • apps/web/src/index.css
  • apps/web/src/macTrafficLightInset.reproduction.test.tsx
  • apps/web/src/macTrafficLightInset.structure.test.ts
  • apps/web/src/macTrafficLightInset.test.ts
  • apps/web/src/macTrafficLightInset.ts
  • apps/web/src/markdown-list-indentation.test.tsx
  • apps/web/src/markdown-list-indentation.ts
  • apps/web/src/statusMotion.structure.test.tsx
  • packages/contracts/src/ipc.ts
  • packages/contracts/src/ipc.typecheck.ts
  • packages/contracts/src/model.test.ts
  • packages/contracts/src/model.ts
  • packages/shared/package.json
  • packages/shared/src/model.test.ts
  • packages/shared/src/modelCompatibility.test.ts
  • packages/shared/src/modelCompatibility.ts

Comment thread apps/server/src/provider/claudeSubscriptionProbe.ts
Comment thread apps/web/src/components/BranchToolbarBranchSelector.browser.tsx Outdated
Comment thread apps/web/src/components/BranchToolbarBranchSelector.tsx
Comment thread apps/web/src/components/chat/DiffStatLabel.logic.ts
Comment thread apps/web/src/components/chat/DiffStatLabel.tsx
Comment thread apps/web/src/components/chat/ProviderModelPicker.tsx
Comment thread apps/web/src/components/DiffPanel.tsx Outdated
Comment thread apps/web/src/markdown-list-indentation.ts Outdated
Comment thread apps/web/src/statusMotion.structure.test.tsx Outdated
Comment thread packages/shared/src/modelCompatibility.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/shared/src/modelCompatibility.ts (1)

80-97: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Message text still hardcodes "Claude Code" despite generic gating.

The minimumProviderVersion gate is now provider/model-agnostic, but the reason string is hardcoded to "Update Claude Code to ...". A future model from a different provider (e.g. cursor, opencode) with a minimumProviderVersion would surface a message referencing the wrong product, with no compile-time signal to catch it — mirroring the original model-name hardcoding concern that was just fixed via modelDisplayName.

Consider deriving the product/provider name the same way the model name is now resolved (e.g. an input-provided display name or a provider-name lookup) instead of the literal string.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/shared/src/modelCompatibility.ts` around lines 80 - 97, The reason
message in resolveModelCompatibility still hardcodes “Claude Code” for the
generic minimumProviderVersion gate. Derive the product/provider display name
from input or the existing provider-name lookup, then use that resolved name in
the update prompt while preserving the current version and model display-name
behavior.
apps/web/src/components/BranchToolbarBranchSelector.tsx (1)

767-826: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Move Base UI’s highlighted item on End instead of only scrolling.

Pressing End only updates highlightedBranchIndexRef and calls scrollToIndex, but Base UI moves the combobox highlight through ArrowDown handling. The viewport can jump to the last branch while aria-activedescendant still points at the previously selected item, so Enter can select the wrong branch and screen readers won’t announce the visible last item. Dispatch synthetic ArrowDown key events for the remaining distance, and prevent the default End behavior if this handler should be the final list-navigation handling. For large lists, consider batching the dispatch loop across microtasks to avoid blocking the UI.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/components/BranchToolbarBranchSelector.tsx` around lines 767 -
826, Update handleBranchInputKeyDown so End moves Base UI’s active combobox
highlight to the final branch, not just highlightedBranchIndexRef and the
virtualizer viewport: prevent the default End behavior and dispatch the required
synthetic ArrowDown events for the remaining distance from the current active
index. Preserve the existing PageUp/PageDown behavior, and consider batching
large End movements across microtasks to avoid blocking the UI.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/web/src/components/chat/DiffStatLabel.logic.ts`:
- Around line 33-40: Update the pluralization in the diff-stat label logic to
use normalizedAdditions === 1 and normalizedDeletions === 1 for the English noun
labels, removing the locale-dependent Intl.PluralRules decision. Continue
passing locales only to formatExactDiffCount, and add a regression test covering
fr-FR with zero counts.

---

Outside diff comments:
In `@apps/web/src/components/BranchToolbarBranchSelector.tsx`:
- Around line 767-826: Update handleBranchInputKeyDown so End moves Base UI’s
active combobox highlight to the final branch, not just
highlightedBranchIndexRef and the virtualizer viewport: prevent the default End
behavior and dispatch the required synthetic ArrowDown events for the remaining
distance from the current active index. Preserve the existing PageUp/PageDown
behavior, and consider batching large End movements across microtasks to avoid
blocking the UI.

In `@packages/shared/src/modelCompatibility.ts`:
- Around line 80-97: The reason message in resolveModelCompatibility still
hardcodes “Claude Code” for the generic minimumProviderVersion gate. Derive the
product/provider display name from input or the existing provider-name lookup,
then use that resolved name in the update prompt while preserving the current
version and model display-name behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a04d8074-9a21-4f19-98cf-22a847ed0094

📥 Commits

Reviewing files that changed from the base of the PR and between fcdaeba and f9bcbc8.

📒 Files selected for processing (22)
  • apps/server/src/provider/claudeSubscriptionProbe.test.ts
  • apps/server/src/provider/claudeSubscriptionProbe.ts
  • apps/web/src/components/BranchToolbarBranchSelector.browser.tsx
  • apps/web/src/components/BranchToolbarBranchSelector.tsx
  • apps/web/src/components/DiffPanel.tsx
  • apps/web/src/components/chat/DiffStatLabel.browser.tsx
  • apps/web/src/components/chat/DiffStatLabel.consumers.test.ts
  • apps/web/src/components/chat/DiffStatLabel.logic.test.ts
  • apps/web/src/components/chat/DiffStatLabel.logic.ts
  • apps/web/src/components/chat/DiffStatLabel.tsx
  • apps/web/src/components/chat/DiffStatLabel.visual.browser.tsx
  • apps/web/src/components/chat/MessagesTimeline.browser.tsx
  • apps/web/src/components/chat/MessagesTimeline.test.tsx
  • apps/web/src/components/chat/MessagesTimeline.tsx
  • apps/web/src/components/chat/ProviderModelPicker.logic.test.ts
  • apps/web/src/components/chat/ProviderModelPicker.logic.ts
  • apps/web/src/components/chat/ProviderModelPicker.tsx
  • apps/web/src/markdown-list-indentation.test.tsx
  • apps/web/src/markdown-list-indentation.ts
  • apps/web/src/statusMotion.structure.test.tsx
  • packages/shared/src/modelCompatibility.test.ts
  • packages/shared/src/modelCompatibility.ts

Comment thread apps/web/src/components/chat/DiffStatLabel.logic.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
apps/web/src/components/BranchToolbarBranchSelector.tsx (2)

767-825: 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

Extract the page-size navigation math into a testable .logic.ts module.

handleBranchInputKeyDown embeds a non-trivial pure algorithm (deriving currentIndex from DOM state, walking estimateBranchItemSize to find targetIndex within a viewport budget) directly inside a component useCallback. Elsewhere in this PR, similarly complex logic is intentionally split into standalone *.logic.ts modules with colocated *.logic.test.ts unit tests (e.g. ProviderModelPicker.logic.ts, DiffStatLabel.logic.ts), enabling fast, precise unit coverage instead of relying solely on the current full-browser DOM tests in BranchToolbarBranchSelector.browser.tsx.

Consider extracting a pure function like computePageTargetIndex({ currentIndex, direction, lastIndex, viewportHeight, estimateItemSize }) that the component wires up, leaving only DOM/event plumbing (aria-activedescendant lookup, event dispatch) in the component.

As per coding guidelines, "Keep logic testable outside React where existing *.logic.test.ts files show that pattern in apps/web."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/components/BranchToolbarBranchSelector.tsx` around lines 767 -
825, Extract the pure page-navigation calculation from handleBranchInputKeyDown
into a colocated .logic.ts function, such as computePageTargetIndex, accepting
the current index, direction, last index, viewport height, and item-size
estimator and returning the target index. Keep DOM lookup, event
prevention/dispatch, and virtualizer scrolling in the component, and add focused
unit tests in the corresponding .logic.test.ts covering PageUp, PageDown, End,
boundaries, and viewport limits.

Source: Coding guidelines


664-673: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Row-height constants (28/44/48/224) are duplicated across JS and Tailwind classes.

estimateBranchItemSize hardcodes 28/44/48, the fallback viewport height 224 is repeated at Line 784 and initialRect.height (Line 681), and the same pixel values are re-encoded as Tailwind classes (h-7/h-11/h-12) at Lines 842 and 886. These five call sites must stay manually in sync; if any single one drifts (e.g., a Tailwind class is bumped without updating the estimator), the virtualizer's scroll math and PageDown/PageUp/End targeting silently desync from the rendered rows.

Extract shared named constants (e.g. BRANCH_ROW_HEIGHT, PR_ROW_HEIGHT, BRANCH_ROW_HEIGHT_WITH_SUMMARY, DEFAULT_VIEWPORT_HEIGHT) and reuse them for both the estimator/height classes and the keyboard-nav fallback.

♻️ Proposed direction
+const BRANCH_ROW_HEIGHT = 28;
+const PR_ROW_HEIGHT = 44;
+const BRANCH_ROW_HEIGHT_WITH_SUMMARY = 48;
+const DEFAULT_BRANCH_VIEWPORT_HEIGHT = 224;
+
 const estimateBranchItemSize = useCallback(
   (index: number) => {
     const itemValue = filteredBranchPickerItems[index];
-    if (!itemValue) return 28;
-    if (itemValue === checkoutPullRequestItemValue) return 44;
+    if (!itemValue) return BRANCH_ROW_HEIGHT;
+    if (itemValue === checkoutPullRequestItemValue) return PR_ROW_HEIGHT;
     const branch = branchByName.get(itemValue);
-    return branch && getCurrentBranchChangeSummary(branch, branchStatusQuery.data) ? 48 : 28;
+    return branch && getCurrentBranchChangeSummary(branch, branchStatusQuery.data)
+      ? BRANCH_ROW_HEIGHT_WITH_SUMMARY
+      : BRANCH_ROW_HEIGHT;
   },
   [...],
 );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/components/BranchToolbarBranchSelector.tsx` around lines 664 -
673, Extract shared named constants for branch row, pull-request row, summary
row, and default viewport heights, then use them in estimateBranchItemSize,
initialRect, and the keyboard-navigation fallback instead of duplicated numeric
literals. Update the rendered row height classes near the branch and
pull-request item renderers to derive from the same constants or a shared
height-to-class mapping, preserving the current 28/44/48/224 pixel behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/web/src/components/BranchToolbarBranchSelector.browser.tsx`:
- Around line 185-204: Consolidate the keyboard event helpers by introducing or
reusing a parameterized dispatch helper that accepts the input element and key
value, then remove the near-duplicate dispatchEnd, dispatchEnter,
dispatchPageDown, and dispatchPageUp implementations. Update every call site to
invoke the shared helper with the appropriate key, preserving existing event
options and behavior.

---

Outside diff comments:
In `@apps/web/src/components/BranchToolbarBranchSelector.tsx`:
- Around line 767-825: Extract the pure page-navigation calculation from
handleBranchInputKeyDown into a colocated .logic.ts function, such as
computePageTargetIndex, accepting the current index, direction, last index,
viewport height, and item-size estimator and returning the target index. Keep
DOM lookup, event prevention/dispatch, and virtualizer scrolling in the
component, and add focused unit tests in the corresponding .logic.test.ts
covering PageUp, PageDown, End, boundaries, and viewport limits.
- Around line 664-673: Extract shared named constants for branch row,
pull-request row, summary row, and default viewport heights, then use them in
estimateBranchItemSize, initialRect, and the keyboard-navigation fallback
instead of duplicated numeric literals. Update the rendered row height classes
near the branch and pull-request item renderers to derive from the same
constants or a shared height-to-class mapping, preserving the current
28/44/48/224 pixel behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 4edfe30e-9711-4a97-b705-991412bfdea0

📥 Commits

Reviewing files that changed from the base of the PR and between f9bcbc8 and 756b9d0.

📒 Files selected for processing (8)
  • apps/web/src/components/BranchToolbarBranchSelector.browser.tsx
  • apps/web/src/components/BranchToolbarBranchSelector.tsx
  • apps/web/src/components/chat/DiffStatLabel.logic.test.ts
  • apps/web/src/components/chat/DiffStatLabel.logic.ts
  • apps/web/src/components/chat/ProviderModelPicker.browser.tsx
  • apps/web/src/components/chat/ProviderModelPicker.tsx
  • packages/shared/src/modelCompatibility.test.ts
  • packages/shared/src/modelCompatibility.ts

Comment thread apps/web/src/components/BranchToolbarBranchSelector.browser.tsx Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/web/src/components/BranchToolbarBranchSelector.tsx (1)

779-832: 🚀 Performance & Scalability | 🟠 Major | 🏗️ Heavy lift

Synthetic End jump can dispatch over 40 keydown events.

At line 811, movementCount uses Math.abs(targetIndex - currentIndex), so for End this becomes the remaining items from the current active index. With virtualized lists enabled at over 40 branches, pressing End synchronously fires hundreds of Arrow/End keydown events before the final scroll, and Base UI may emit onItemHighlighted for each highlight step. Limit the event-dispatch loop to the PageUp/PageDown deltas, and find a way to jump End without simulating one Arrow key per row if possible.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/components/BranchToolbarBranchSelector.tsx` around lines 779 -
832, Update handleBranchInputKeyDown so the synthetic keydown loop only
dispatches events for PageUp/PageDown movement deltas; do not simulate one
ArrowDown event per item for End. Handle End by directly updating the
highlighted index and scrolling to the final item while preserving the existing
end alignment and PageUp/PageDown behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@apps/web/src/components/BranchToolbarBranchSelector.tsx`:
- Around line 779-832: Update handleBranchInputKeyDown so the synthetic keydown
loop only dispatches events for PageUp/PageDown movement deltas; do not simulate
one ArrowDown event per item for End. Handle End by directly updating the
highlighted index and scrolling to the final item while preserving the existing
end alignment and PageUp/PageDown behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 6c37f0cb-827f-4c1d-9d20-a39ef731d530

📥 Commits

Reviewing files that changed from the base of the PR and between 756b9d0 and 655ee2d.

📒 Files selected for processing (4)
  • apps/web/src/components/BranchToolbarBranchSelector.browser.tsx
  • apps/web/src/components/BranchToolbarBranchSelector.logic.test.ts
  • apps/web/src/components/BranchToolbarBranchSelector.logic.ts
  • apps/web/src/components/BranchToolbarBranchSelector.tsx

@Jay1

Jay1 commented Jul 30, 2026

Copy link
Copy Markdown
Owner Author

Follow-up on CodeRabbit review 4817427762 (End navigation performance): we checked Base UI 1.5’s public Combobox API and ran focused native-End and ARIA-only probes. In those probes, native End did not move the active descendant, while changing aria-activedescendant alone did not update Base UI’s internal highlight/immediate-Enter target. Base UI 1.5 does not expose a public imperative highlight setter.

For now, JCode retains the synthetic Arrow loop so Base UI’s owned highlight, the active descendant, the virtualizer, and immediate Enter remain aligned. The loop is finite and bounded by the remaining list distance; this is not a claim of constant-time behavior. We recommend replacing it when upstream exposes public highlight control. The bounded navigation oracle (363,375 zero-delta cases), 10 repeated focused runs, full 342-test browser suite, and exact-head CI—including desktop package and preload verification—are green.

@Jay1
Jay1 merged commit 1a2f408 into main Jul 30, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant