Skip to content

fix(app): stabilize shell navigation state#424

Merged
Astro-Han merged 8 commits into
devfrom
codex/fix-i420-shell-navigation
May 4, 2026
Merged

fix(app): stabilize shell navigation state#424
Astro-Han merged 8 commits into
devfrom
codex/fix-i420-shell-navigation

Conversation

@Astro-Han

@Astro-Han Astro-Han commented May 4, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds a focused shell navigation owner for New session, Open session, and Settings actions.
  • Exposes shell owner actions through ShellSurfaceContext so the Opening recovery state also routes New session through the same owner instead of local route navigation.
  • Routes normal sidebar session and workspace New session clicks through the shell owner while preserving anchor fallback for modified clicks and new-tab behavior.
  • Renames the shared link preflight helper from sidebar-specific wording to shell-owner wording now that it covers session and new-session links.
  • Makes session visible identity follow the route immediately instead of keeping the previous session visible while target messages load.
  • Shows a visible Opening session... recovery state with Retry and New session actions when the target session identity is selected but its messages are not ready.
  • Hides the composer while a target session is still opening, so users cannot submit into a not-ready route identity.
  • Removes the fixed recent-message lookback from question fallback recovery so missed question events can recover from older running question parts.
  • Removes small stale abstractions left by the first pass: the unused project release reason and nextVisibleSessionID() wrapper.

Why

Fixes #420.

Related: #419 for the stale running-question fallback path. This PR does not rewrite the full question recovery model.

The installed app could enter a shell-stuck state where global navigation looked clickable but did not change the visible page. The risky invariant was that the route could point at a new shell identity while the session view kept rendering the previous session as a loading bridge.

This PR favors trustworthy shell identity over visual continuity: when the route targets a session, the visible identity is that session; when the target data is not ready, the user sees a target loading/recovery state instead of stale content.

Related Issue

Fixes #420

Related: #419

Human Review Status

Pending. A human should make the final merge decision after reviewing the final diff and verification evidence.

Review Focus

Please check:

  • createShellNavigation is the right narrow owner for shell actions without over-growing layout.tsx.
  • Sidebar session rows, workspace New session entries, and the Opening recovery New session action call the shell owner for ordinary navigation, while link-backed entries still behave like links for modified clicks.
  • ShellSurfaceContext is an acceptable minimal bridge for session-page recovery actions before a full ShellRoute / ShellController rewrite.
  • session-view-controller no longer permits stale visible session identity while preserving loading readiness.
  • SessionMainView shows the target loading/recovery state only while route messages are not ready and keeps the composer hidden during that state.
  • The delayed-target sidebar E2E covers the main [Bug] Shell can get stuck and block session navigation #420 invariant: URL changes to the target session, old session text disappears, composer is hidden, and New session recovery works while target messages are blocked.
  • The question fallback full-session scan is acceptable for the current in-memory message window and does not introduce meaningful hot-path risk.

Risk Notes

Medium app-flow risk. This changes the session transition contract: users should see the target session loading state instead of the previous session during a not-ready route transition.

releaseTransientShellLocks is intentionally narrow in this PR: it clears the layout sizing lock and pending sizing timeout only. Modal, drag, permission, and question owners are not widened here; question and permission blockers remain session-local and must not block shell navigation.

Settings still uses a local surface signal, now entered through the shell owner. A full ShellRoute / ShellController state machine, broad interaction-lock registry, durable blocker recovery source, visible question recovery UI, and soft timeout/error state for long Opening transitions are left as follow-up architecture work to avoid turning this P0 bugfix into a broad frontend rewrite.

The broader settings E2E command also hit an existing unknown theme ids migrate to pawwork and clear cached css failure unrelated to this change. The narrower shell navigation E2E checks passed.

How To Verify

Install deps: bun install --frozen-lockfile -> completed
Focused unit coverage: bun --cwd packages/app test src/pages/layout/sidebar-item-navigation.test.ts src/pages/layout/shell-navigation.test.ts src/pages/session/session-view-controller.test.ts src/pages/session/timeline-session-state.test.ts src/pages/session/session-main-view.test.ts -> 797 passed, 0 failed
App typecheck: bun --cwd packages/app typecheck -> passed
Focused delayed-opening E2E: bun --cwd packages/app test:e2e e2e/sidebar/sidebar-session-links.spec.ts --grep "opening a delayed sidebar session" -> 1 passed
Focused sidebar E2E: bun --cwd packages/app test:e2e e2e/sidebar/sidebar-session-links.spec.ts -> 3 passed
Diff check: git diff --check -> passed
Earlier broader E2E note: bun --cwd packages/app test:e2e e2e/sidebar/sidebar-session-links.spec.ts e2e/settings/settings.spec.ts --grep "New|Settings|session" -> 18 passed, 3 skipped, 1 existing settings theme-cache failure

Screenshots or Recordings

Not applicable. This is shell navigation behavior with a small loading/recovery-state addition.

Checklist

  • Human review status is stated above as pending, approved, or not required
  • I linked the related issue, or stated why there is no issue
  • This PR has type, scope, and priority labels, or I requested maintainer labeling
  • I described the review focus and any meaningful risks
  • I listed the relevant verification steps and the key result for each
  • I did not introduce unrelated refactors, dependencies, generated files, or file changes beyond the stated scope
  • I manually checked visible UI or copy changes when needed, with screenshots or recordings
  • I considered macOS and Windows impact for desktop, packaging, updater, signing, paths, shell, or permissions changes
  • I called out docs, release notes, dependencies, permissions, credentials, deletion behavior, generated content, or local file changes when relevant
  • I reviewed the final diff for unrelated changes and suspicious dependency changes
  • I am targeting dev, and my PR title and commit messages use Conventional Commits in English

Summary by CodeRabbit

  • New Features
    • Session-opening UI now shows Retry and New Session actions; sidebar links can open or create sessions via the shell.
  • Bug Fixes
    • Visible session identity follows the navigation route during loading/transitions.
    • Fallback now scans full message history to better recover running question sessions.
  • Refactor
    • Centralized shell navigation for session/new-session/settings with unified transient-lock release and choose-project fallback.
  • Tests
    • Added/updated tests for navigation flows, sidebar link behavior, and session-opening state.
  • Chores
    • Added session-opening translations (en/zh).

@Astro-Han Astro-Han added bug Something isn't working P0 Blocking / highest priority app Application behavior and product flows ui Design system and user interface labels May 4, 2026
@coderabbitai

coderabbitai Bot commented May 4, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: b020f89a-6ed9-4b11-a75f-a71199c450e3

📥 Commits

Reviewing files that changed from the base of the PR and between 90f9a0b and 0c057d2.

📒 Files selected for processing (1)
  • packages/app/e2e/sidebar/sidebar-session-links.spec.ts

📝 Walkthrough

Walkthrough

Centralizes shell navigation into createShellNavigation (open new/session/settings) that always calls a transient-lock release before navigation or fallback; wires sidebar and shell surface to use it. Aligns visible session identity with route during loading, exposes session-opening UI state, and removes question-fallback lookback.

Changes

Shell Navigation, Sidebar & Session Visibility

Layer / File(s) Summary
Data Shape / Types
packages/app/src/pages/layout/shell-navigation.ts, packages/app/src/context/shell-surface.tsx
Adds ShellNavigationReleaseReason variant "choose-project", ShellNavigationSession type; expands ShellSurfaceContextValue to include openNewSession(directory?) and openSession(session?) (imports Session).
Core Navigation Logic
packages/app/src/pages/layout/shell-navigation.ts
Implements createShellNavigation with openNewSession, openSession, openSettings; each calls releaseTransientLocks(reason) then navigates or calls chooseProject/openSettingsSurface.
Layout Wiring / Integration
packages/app/src/pages/layout.tsx
Creates shellNavigation via createShellNavigation; delegates navigateToSession/openPawworkHome/openSettings to it; exposes openSession/openNewSession through workspaceSidebarCtx and ShellSurfaceContext.Provider.
Sidebar Click Handling
packages/app/src/pages/layout/sidebar-item-navigation.ts, packages/app/src/pages/layout/sidebar-items.tsx, packages/app/src/pages/layout/pawwork-sidebar.tsx, packages/app/src/pages/layout/sidebar-workspace.tsx
Adds ShellLinkClick/ShellOwnerLinkEvent, defaultSessionHref/defaultNewSessionHref, shouldUseShellOwnerForLink, openShellLinkWithOwner; SessionItem/NewSessionItem accept optional hrefForSession/onOpenSession/onOpenNewSession and route clicks through openShellLinkWithOwner; workspace context now exposes openSession and openNewSession.
Session View State Simplification
packages/app/src/pages/session/session-view-controller.ts
Removes prior visible-directory/session inputs; nextSessionViewState sets visibleSessionID directly from route and transitioning from route readiness; visibleReady simplified to routeReady.
Timeline / Transitioning Prop
packages/app/src/pages/session/use-session-timeline-data.ts
Returns transitioning (from sessionView.transitioning) alongside timeline data.
Question-fallback Scan
packages/app/src/pages/session/blockers/question-fallback.ts
Removes lookback and QUESTION_FALLBACK_LOOKBACK_MESSAGES; scans entire message history in reverse to find running question parts.
Session Main View UI
packages/app/src/pages/session/session-main-view.tsx, packages/app/src/pages/session/session-main-view-state.ts
Adds shouldShowSessionOpeningState; extends SessionMainView props (routeSessionID, routeReady, transitioning, timelineMessagesReady, onRetryOpenSession, onOpenNewSession); renders explicit "Opening session..." UI and hides composer during opening state.
Routing Props / Call Sites
packages/app/src/pages/session.tsx
Wires routeSessionID, routeReady, transitioning, timelineMessagesReady, and handlers (retryOpenRouteSession, openNewRouteSession) into SessionMainView.
i18n
packages/app/src/i18n/en.ts, packages/app/src/i18n/zh.ts
Adds session.opening (EN/ZH) and common.retry (EN).
Tests & E2E
packages/app/src/pages/..., packages/app/e2e/sidebar/sidebar-session-links.spec.ts
Adds unit tests for createShellNavigation (order and choose-project fallback), sidebar click handling tests, updates session-view-controller tests to align visible identity with route, updates question-fallback test to expect older running-question recovery, and adds an e2e asserting session-opening UI for delayed session loads.

Sequence Diagram(s)

sequenceDiagram
  participant Layout as Layout Component
  participant Shell as createShellNavigation
  participant Navigator as Router/Navigator
  participant Locks as TransientLocks
  participant Choose as chooseProject
  participant Settings as SettingsSurface

  Layout->>Shell: openNewSession(optional dir)
  Shell->>Locks: releaseTransientLocks("new-session" or "choose-project")
  alt no project root
    Shell->>Choose: chooseProject()
  else has project root
    Shell->>Navigator: navigate(newSessionRoute(root))
  end

  Layout->>Shell: openSession(session)
  Shell->>Locks: releaseTransientLocks("session")
  Shell->>Navigator: navigate(openSessionRoute(dir, id))

  Layout->>Shell: openSettings()
  Shell->>Locks: releaseTransientLocks("settings")
  Shell->>Settings: openSettingsSurface()
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

  • #414 — Implements a navigation abstraction and transient-lock release contract similar to that issue's objectives.
  • #413 — Centralizes shell navigation and rewires sidebar/layout to use explicit openSession/openNewSession flows described there.

Possibly related PRs

  • #415 — Shares routing helpers and navigation/lock handling changes used here.
  • #329 — Related changes to session view/controller exports and visible-vs-route identity adjustments.
  • #407 — Related to new-session routing and navigation wiring.

Suggested labels

P1

"I’m a rabbit who hops through code so light,
I free the locks and guide the route tonight.
Sessions open, settings show, no fear—
I nibble stale state and make flows clear. 🐇✨"

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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
Title check ✅ Passed The title 'fix(app): stabilize shell navigation state' accurately describes the main objective: fixing shell navigation stability by establishing a focused navigation owner and recovering from shell-stuck states.
Description check ✅ Passed The PR description comprehensively covers all required template sections including Summary, Why, Related Issue, Review Focus, Risk Notes, and How To Verify with detailed verification steps and results.
Linked Issues check ✅ Passed The PR addresses all primary objectives from issue #420: adds a focused shell navigation owner (createShellNavigation), prevents shell-stuck failures via synchronized route/visible identity, surfaces an explicit recovery state, reduces layout.tsx responsibility, and provides regression coverage with unit tests and E2E checks.
Out of Scope Changes check ✅ Passed All changes are directly scoped to shell navigation stabilization, session identity synchronization, recovery UI, fallback improvements, and removing stale abstractions. No unrelated refactors, dependencies, or generated files were introduced.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/fix-i420-shell-navigation

Review rate limit: 8/10 reviews remaining, refill in 8 minutes and 21 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request introduces a centralized shellNavigation utility to manage application navigation and transient locks, while also refactoring the session view logic. Key changes include removing the 'lookback' window for question fallback sessions and simplifying the SessionViewController by removing the logic that preserved the previous session's visibility during transitions. The review feedback suggests further streamlining the SessionViewController by inlining the now-trivial nextVisibleSessionID function and simplifying the transitioning and visibleReady logic to reflect the new immediate alignment with the target route.

Comment thread packages/app/src/pages/session/session-view-controller.ts Outdated
Comment thread packages/app/src/pages/session/session-view-controller.ts Outdated
Comment thread packages/app/src/pages/session/session-view-controller.ts Outdated

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/app/src/pages/layout/shell-navigation.test.ts (1)

54-67: ⚡ Quick win

Add the explicit-directory fallback case too.

This only exercises the currentProjectRoot() failure path because openNewSession() is called without an argument. The sibling branch for resolveProjectRoot(directory) is still unpinned when an explicit directory cannot be resolved.

🧪 Suggested companion test
   test("falls back to project chooser when no directory can be resolved for a new session", () => {
     const calls: string[] = []
     const shell = createShellNavigation({
       navigate: (route) => calls.push(`navigate:${route}`),
       releaseTransientLocks: (reason) => calls.push(`release:${reason}`),
       resolveProjectRoot: () => "",
       currentProjectRoot: () => undefined,
       chooseProject: () => calls.push("chooseProject"),
       openSettingsSurface: () => calls.push("settings"),
     })

     shell.openNewSession()

     expect(calls).toEqual(["release:new-session", "chooseProject"])
   })
+
+  test("falls back to project chooser when an explicit directory cannot be resolved", () => {
+    const calls: string[] = []
+    const shell = createShellNavigation({
+      navigate: (route) => calls.push(`navigate:${route}`),
+      releaseTransientLocks: (reason) => calls.push(`release:${reason}`),
+      resolveProjectRoot: () => undefined,
+      currentProjectRoot: () => "/current",
+      chooseProject: () => calls.push("chooseProject"),
+      openSettingsSurface: () => calls.push("settings"),
+    })
+
+    shell.openNewSession("/repo")
+
+    expect(calls).toEqual(["release:new-session", "chooseProject"])
+  })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/app/src/pages/layout/shell-navigation.test.ts` around lines 54 - 67,
Add a companion test that exercises the explicit-directory fallback path:
createShellNavigation with resolveProjectRoot returning "" and
currentProjectRoot returning undefined (or as appropriate), then call
shell.openNewSession("/some/dir") (i.e., pass an explicit directory) and assert
the calls include releasing transient locks and choosing project (e.g.,
["release:new-session","chooseProject"]); this ensures the
resolveProjectRoot(directory) branch is covered in addition to the existing
currentProjectRoot() failure path. Use the same helpers (createShellNavigation,
resolveProjectRoot, currentProjectRoot, chooseProject, openNewSession) and
mirror the structure of the existing test.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/app/src/pages/session/session-view-controller.ts`:
- Around line 23-36: In use-session-timeline-data.ts the various memos and
effects (sessionInfo, messages, diffs, revertMessageID,
historyMore/historyLoading and the createEffect that reads
lastUserMessage()?.id) dereference input.sync.session and input.sync.data.*
before the session messages are guaranteed to be loaded; update each to first
check messagesReady and if false return safe defaults (e.g., undefined for
sessionInfo/revertMessageID, [] for messages/diffs, false for historyLoading,
0/undefined for counts) and only access input.sync.session.get(id) or
input.sync.data.message[id] when messagesReady is true so no properties are read
from uninitialized state. Ensure the createEffect depends on messagesReady (or
guards lastUserMessage()) so it won’t run against unready data.

---

Nitpick comments:
In `@packages/app/src/pages/layout/shell-navigation.test.ts`:
- Around line 54-67: Add a companion test that exercises the explicit-directory
fallback path: createShellNavigation with resolveProjectRoot returning "" and
currentProjectRoot returning undefined (or as appropriate), then call
shell.openNewSession("/some/dir") (i.e., pass an explicit directory) and assert
the calls include releasing transient locks and choosing project (e.g.,
["release:new-session","chooseProject"]); this ensures the
resolveProjectRoot(directory) branch is covered in addition to the existing
currentProjectRoot() failure path. Use the same helpers (createShellNavigation,
resolveProjectRoot, currentProjectRoot, chooseProject, openNewSession) and
mirror the structure of the existing test.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 7701fbec-d0c5-49f1-ac82-54b7886d8b78

📥 Commits

Reviewing files that changed from the base of the PR and between a87364b and 14cfeda.

📒 Files selected for processing (7)
  • packages/app/src/pages/layout.tsx
  • packages/app/src/pages/layout/shell-navigation.test.ts
  • packages/app/src/pages/layout/shell-navigation.ts
  • packages/app/src/pages/session/blockers/question-fallback.test.ts
  • packages/app/src/pages/session/blockers/question-fallback.ts
  • packages/app/src/pages/session/session-view-controller.test.ts
  • packages/app/src/pages/session/session-view-controller.ts

Comment thread packages/app/src/pages/session/session-view-controller.ts Outdated
@Astro-Han Astro-Han added the harness Model harness, prompts, tool descriptions, and session mechanics label May 4, 2026

@coderabbitai coderabbitai Bot left a comment

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.

🧹 Nitpick comments (1)
packages/app/src/pages/layout/shell-navigation.test.ts (1)

54-66: ⚡ Quick win

resolveProjectRoot mock in this case is not exercised.

On Line 65, openNewSession() is called without a directory, so Line 59’s resolveProjectRoot: () => "" never runs. This makes the setup misleading and leaves the explicit-directory + empty-string fallback path untested.

♻️ Suggested test adjustment
-  test("falls back to project chooser when no directory can be resolved for a new session", () => {
+  test("falls back to project chooser when explicit directory resolves to empty root", () => {
     const calls: string[] = []
     const shell = createShellNavigation({
       navigate: (route) => calls.push(`navigate:${route}`),
       releaseTransientLocks: (reason) => calls.push(`release:${reason}`),
       resolveProjectRoot: () => "",
       currentProjectRoot: () => undefined,
       chooseProject: () => calls.push("chooseProject"),
       openSettingsSurface: () => calls.push("settings"),
     })
 
-    shell.openNewSession()
+    shell.openNewSession("/repo")
 
     expect(calls).toEqual(["release:choose-project", "chooseProject"])
   })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/app/src/pages/layout/shell-navigation.test.ts` around lines 54 - 66,
The test's resolveProjectRoot mock is not actually exercised because
openNewSession() is called with no directory; change the test to call
shell.openNewSession with an explicit directory string (e.g. "/some/dir") so
createShellNavigation's resolveProjectRoot mock (resolveProjectRoot: () => "")
runs and returns the empty string, thereby exercising the explicit-directory +
empty-string fallback path and still asserting that chooseProject is invoked;
reference createShellNavigation, resolveProjectRoot, and openNewSession when
making this change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/app/src/pages/layout/shell-navigation.test.ts`:
- Around line 54-66: The test's resolveProjectRoot mock is not actually
exercised because openNewSession() is called with no directory; change the test
to call shell.openNewSession with an explicit directory string (e.g.
"/some/dir") so createShellNavigation's resolveProjectRoot mock
(resolveProjectRoot: () => "") runs and returns the empty string, thereby
exercising the explicit-directory + empty-string fallback path and still
asserting that chooseProject is invoked; reference createShellNavigation,
resolveProjectRoot, and openNewSession when making this change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: ef9091bf-cc04-4a35-8842-e601c0699b75

📥 Commits

Reviewing files that changed from the base of the PR and between 0606f6e and 2eb551c.

📒 Files selected for processing (2)
  • packages/app/src/pages/layout/shell-navigation.test.ts
  • packages/app/src/pages/session/session-view-controller.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/app/src/pages/session/session-view-controller.ts

@coderabbitai coderabbitai Bot left a comment

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.

🧹 Nitpick comments (1)
packages/app/src/pages/session/session-main-view.tsx (1)

114-127: 💤 Low value

Consider using the Button component for consistency.

The retry and new session buttons use manual styling while the Button component is already imported and used elsewhere in the codebase. Using Button variant="ghost" would ensure consistent styling, focus states, and accessibility behavior across the app.

♻️ Suggested change
-                      <button
-                        type="button"
-                        class="rounded-md border border-border-subtle px-3 py-1 text-13-regular text-text-base transition-colors hover:bg-surface-raised-base-hover focus:outline-none focus-visible:bg-surface-raised-base-hover"
-                        onClick={props.onRetryOpenSession}
-                      >
-                        {props.language.t("common.retry")}
-                      </button>
-                      <button
-                        type="button"
-                        class="rounded-md border border-border-subtle px-3 py-1 text-13-regular text-text-base transition-colors hover:bg-surface-raised-base-hover focus:outline-none focus-visible:bg-surface-raised-base-hover"
-                        onClick={props.onOpenNewSession}
-                      >
-                        {props.language.t("command.session.new")}
-                      </button>
+                      <Button variant="ghost" size="small" onClick={props.onRetryOpenSession}>
+                        {props.language.t("common.retry")}
+                      </Button>
+                      <Button variant="ghost" size="small" onClick={props.onOpenNewSession}>
+                        {props.language.t("command.session.new")}
+                      </Button>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/app/src/pages/session/session-main-view.tsx` around lines 114 - 127,
Replace the two plain <button> elements used for retry and new session with the
shared Button component to ensure consistent styling and accessibility: locate
the elements handling props.onRetryOpenSession and props.onOpenNewSession in
SessionMainView (session-main-view.tsx) and swap them to use Button with
variant="ghost" (or the matching ghost prop the project uses), forwarding the
onClick handlers to Button and keeping the children as
props.language.t("common.retry") and props.language.t("command.session.new");
ensure any class attributes are removed so the Button's built-in styles and
focus behavior are used.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/app/src/pages/session/session-main-view.tsx`:
- Around line 114-127: Replace the two plain <button> elements used for retry
and new session with the shared Button component to ensure consistent styling
and accessibility: locate the elements handling props.onRetryOpenSession and
props.onOpenNewSession in SessionMainView (session-main-view.tsx) and swap them
to use Button with variant="ghost" (or the matching ghost prop the project
uses), forwarding the onClick handlers to Button and keeping the children as
props.language.t("common.retry") and props.language.t("command.session.new");
ensure any class attributes are removed so the Button's built-in styles and
focus behavior are used.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: ee163624-7c2a-4c3f-a92c-7af050f726b4

📥 Commits

Reviewing files that changed from the base of the PR and between dbeeece and 2c42eea.

📒 Files selected for processing (11)
  • packages/app/src/pages/layout.tsx
  • packages/app/src/pages/layout/shell-navigation.ts
  • packages/app/src/pages/layout/sidebar-item-navigation.test.ts
  • packages/app/src/pages/layout/sidebar-item-navigation.ts
  • packages/app/src/pages/layout/sidebar-items.tsx
  • packages/app/src/pages/layout/sidebar-workspace.tsx
  • packages/app/src/pages/session/session-main-view.tsx
  • packages/app/src/pages/session/session-view-controller.ts
  • packages/app/src/pages/session/timeline-session-state.test.ts
  • packages/app/src/pages/session/timeline-session-state.ts
  • packages/app/src/shell-frame-contract.test.ts
💤 Files with no reviewable changes (1)
  • packages/app/src/pages/session/timeline-session-state.ts
✅ Files skipped from review due to trivial changes (1)
  • packages/app/src/pages/layout/shell-navigation.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/app/src/pages/layout/sidebar-item-navigation.test.ts
  • packages/app/src/pages/layout/sidebar-items.tsx

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/app/e2e/sidebar/sidebar-session-links.spec.ts`:
- Around line 138-149: The test registers the message route and may observe
targetMessageRequests > 0 before the sidebar click, so make the assertion verify
the fetch starts after the click: ensure you either reset or reinitialize the
targetMessageRequests counter (or re-register the page.route that increments it)
immediately before clicking the sidebar link, or assert await expect.poll(() =>
targetMessageRequests, { timeout: 0 }).toBe(0) right before
page.locator(`[data-session-id="${target.id}"] a`).first().click(), then click
and assert the counter increases (await expect.poll(() => targetMessageRequests,
{ timeout: 10_000 }).toBeGreaterThan(0)); keep the rest of the flow
(gotoSession, openSidebar, and checking
'[data-component="session-opening-state"]') unchanged.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 9fc230ec-c98a-4924-aa0c-c12d9dde789f

📥 Commits

Reviewing files that changed from the base of the PR and between 2c42eea and 3044fed.

📒 Files selected for processing (1)
  • packages/app/e2e/sidebar/sidebar-session-links.spec.ts

Comment thread packages/app/e2e/sidebar/sidebar-session-links.spec.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app Application behavior and product flows bug Something isn't working harness Model harness, prompts, tool descriptions, and session mechanics P0 Blocking / highest priority ui Design system and user interface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Shell can get stuck and block session navigation

1 participant