Skip to content

feat(site/src): animate agents panels - #30002

Open
tracyjohnsonux wants to merge 10 commits into
mainfrom
sidebar-collapse-motion
Open

tracyjohnsonux wants to merge 10 commits into
mainfrom
sidebar-collapse-motion

Conversation

@tracyjohnsonux

@tracyjohnsonux tracyjohnsonux commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

The agents chats sidebar and right panel now slide open and closed (200ms, ease-out) instead of snapping, including when the window is resized.

  • Toggling either panel animates its width. Content stays pinned at full width during the slide so it moves behind the edge instead of reflowing (and refitting terminals) every frame.
  • Narrowing the window below the lg breakpoint, which auto-closes the right panel, now slides it out.
  • On chat and settings detail routes, crossing the sm breakpoint (where mobile hides the sidebar) slides the left sidebar out or back in.
  • A sidebar squeezed by a narrow window now grows back to the user's saved width when the window widens. Previously it stayed at the squeezed width.
  • Pointer drag-resizing skips the transition so edges track the pointer. Reduced motion is handled by the existing global rule, and Pixel screenshots already disable transitions and animations.
  • Unchanged: closing an expanded (fullscreen) right panel, and the mobile chat-list route, where the sidebar is the main content.
Implementation notes
  • Breakpoint crossings use panel-slide-out / panel-slide-in keyframe animations (in index.css) rather than transitions: the breakpoint's CSS changes before React re-renders, so there is no reliable starting width to transition from. The animations read --panel-width and hold min-width at 0.
  • ResizableChatsSidebarFrame takes isCollapsed and collapses to w-0 + invisible (sm+) instead of sm:hidden so the width can transition; invisible keeps collapsed content out of the tab order and accessibility tree, as sm:hidden did. It also takes viewportSlide ("in"/"out"), driven by AgentsPageLayout on sm crossings. While sliding out, the layout is kept flex-row so the sidebar stays beside the chat.
  • RightPanel's closed state at lg is a zero-width invisible flex item instead of display: none, so the width can transition. Content is pinned to --panel-width while closed or animating open, then released on transitionend.
  • Verified in Chromium by sampling panel widths during toggles and viewport resizes across 1024px and 640px. The width re-clamp and slide-end handling are covered by unit tests.

Generated by Coder Agents on behalf of @tracyjohnsonux.

Slide the agents chats sidebar and right panel open and closed with a
short width transition instead of toggling display. Content is pinned to
its full width during the slide so it moves behind the edge rather than
reflowing every frame.

Window resizing animates too: crossing below the side-by-side breakpoint
slides the right panel out with a keyframe animation, and a left sidebar
that was auto-collapsed to make room for the panel is restored once the
window is wide enough again.
On chat and settings detail routes the mobile layout hides the chats
sidebar. Crossing the sm breakpoint now slides it out or in with keyframe
animations instead of snapping, keeping the layout side by side while it
slides out.

Window-resize clamping now re-derives the sidebar width from the persisted
value, so a sidebar squeezed by a narrow window grows back to the user's
chosen width.
@tracyjohnsonux

Copy link
Copy Markdown
Contributor Author

/coder-agents-review

@coder-agents-review

coder-agents-review Bot commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

Chat: Review posted | View chat
Requested: 2026-09-27 05:25 UTC by @tracyjohnsonux

Review history
  • R1 (2026-09-27): 13 reviewers, 5 Nit, 2 P2, 10 P3, 11 P4, COMMENT. Review
  • R2 (2026-09-27): 13 reviewers, 7 Nit, 2 P2, 15 P3, 18 P4, COMMENT. Review
  • R3 (2026-09-27): 13 reviewers, 7 Nit, 2 P2, 18 P3, 20 P4, COMMENT. Review
  • R4 (2026-09-27): 14 reviewers, 7 Nit, 2 P2, 19 P3, 23 P4, COMMENT. Review
  • R5 (2026-09-27): 13 reviewers, 7 Nit, 2 P2, 19 P3, 24 P4, COMMENT. Review
  • R6 (2026-09-27): 10 reviewers, 7 Nit, 2 P2, 19 P3, 26 P4, COMMENT. Review
  • R7 (2026-09-27): 13 reviewers, 8 Nit, 3 P2, 19 P3, 27 P4, COMMENT. Review

deep-review v0.13.0 | Round 7 | 5dde49d..0757b36

Last posted: Round 7, 57 findings (3 P2, 19 P3, 27 P4, 8 Nit), COMMENT. Review

Finding inventory

Finding inventory: PR #30002

Findings

# Sev Status Location Summary Round Reviewer Posted
CRF-1 P3 Author fixed (c0453ae) AgentsPageLayout.tsx:678 sm crossing slide state and its stuck-slide guard have no test R1 Netero Yes
CRF-2 P3 Author contested; panel closed R2 (1/1 accept) RightPanel.tsx:316 Content pinning and narrow slide-out state in RightPanel have no test R1 Netero Yes
CRF-3 P4 Author contested; panel closed R2 (1/1 accept) RightPanel.tsx:444 Closed lg class drops border-l at the start of the close transition R1 Netero Yes
CRF-4 Nit Author fixed (f5f777a) RightPanel.tsx:348 Separate effect mirrors isSidebarCollapsed into a ref (FE8) R1 Netero Yes
CRF-5 Note Note (body) ResizableChatsSidebarFrame.tsx:134 --panel-width and --agents-left-sidebar-width hold the same value on one element R1 Netero No
CRF-6 OOS Out of scope (body) RightPanel.tsx:263 Right panel resize clamp overwrites the saved right panel width, same squeeze bug as the left sidebar R1 Netero No
CRF-7 P2 Author fixed (f5f777a) RightPanel.tsx:347 Auto-collapse flag is a RightPanel ref, lost on remount (chat switch, loading view swap), so the sidebar is never restored R1 Nami P2, Pariston P2, Luffy P3, Mafuuu P3, Hisoka P3, Chopper P3 Yes
CRF-8 P2 Author fixed (f5f777a) RightPanel.tsx:389 Restore check uses the stored sidebar width, not the rendered width; divergence (storage failure, other tab) loops collapse/restore R1 Hisoka P3 Yes
CRF-9 P3 Author fixed (f5f777a) RightPanel.tsx:390 Restore reserves only MIN_WIDTH for the panel, so a wider panel is squeezed and the squeezed width is saved R1 Mafuuu Yes
CRF-10 P3 Author fixed (f5f777a) ResizableChatsSidebarFrame.tsx:57 handleResize reloads width from storage, so a failed write loses the dragged width on every resize R1 Hisoka P3, Mafuuu P4, Chopper P4 Yes
CRF-11 P3 Author contested; panel closed R2 (1/1 accept) AgentsPageLayout.tsx:678 Breakpoint-crossing slides add state machinery and stale-state paths for a rare trigger R1 Luffy Yes
CRF-12 P3 Author fixed (f5f777a) RightPanel.test.tsx:359 1040px no-restore check reads the count before the component's frame, so broken hysteresis passes R1 Bisky Yes
CRF-13 P3 Author fixed (f5f777a) RightPanel.test.tsx:370 No test for a user collapse after an auto-collapse; the ref reset effect can be deleted R1 Bisky Yes
CRF-14 P4 Author fixed (f5f777a) AgentsPageLayout.tsx:700 Guard masks a stale sidebarViewportSlide without clearing it, so the slide replays later R1 Hisoka, Komugi Yes
CRF-15 P4 Author fixed (f5f777a) RightPanel.tsx:340 isSlidingOutOnNarrow stays true after a reopen mid-slide, so the next close below lg replays the slide-out R1 Komugi Yes
CRF-16 P4 Author fixed (f5f777a) RightPanel.tsx:321 isAnimatingOpen is set below lg where no width transition clears it R1 Komugi Yes
CRF-17 P4 Author fixed (f5f777a) RightPanel.tsx:432 transitioncancel from a replaced close unpins content during the reopen slide R1 Mafuuu Yes
CRF-18 P4 Author fixed (f5f777a) RightPanel.tsx:396 Redundant second writer clears sidebarAutoCollapsed in the restore branch R1 Bisky Yes
CRF-19 P4 Author fixed (f5f777a) ResizableChatsSidebarFrame.tsx:56 useEffectEvent wrapper no longer needed; handleResize reads no props or state R1 Ging-React Yes
CRF-20 Nit Author fixed (f5f777a) RightPanel.tsx:323 React.TransitionEvent/AnimationEvent namespace types; file imports event types by name R1 Ging-TS, Ging-React Yes
CRF-21 P3 Author fixed (f5f777a) RightPanel.tsx:333 isSlidingOutOnNarrow and isNarrowSlideOut differ in word order; only one is safe to render R1 Gon Yes
CRF-22 P3 Author fixed (f5f777a) AgentsPageLayout.tsx:696 Guard comment is ambiguous and omits when animationend is skipped R1 Gon P3, Leorio P4 Yes
CRF-23 P3 Author fixed (f5f777a) ResizableChatsSidebarFrame.tsx:24 viewportSlide doc covers only "out", uses caller terms, omits the caller's reset duty R1 Gon P3, Leorio Nit Yes
CRF-24 Nit Dropped by orchestrator (comment states why the block exists, which the useMediaQuery line does not show) AgentsPageLayout.tsx:678 Block comment restates the code R1 Gon P2 No
CRF-25 Nit Dropped by orchestrator (PR corrected an existing harness doc to match new behavior; it names the restore purpose the harness name omits) RightPanel.test.tsx:52 Harness doc restates the harness body R1 Gon P2 No
CRF-26 P4 Author fixed (f5f777a) RightPanel.tsx:331 lg breakpoint read from matchMedia and from innerWidth < 1024 R1 Gon Yes
CRF-27 P4 Author fixed (f5f777a) index.css:197 200ms slide duration written in four unlinked places R1 Gon Yes
CRF-28 Nit Author fixed (f5f777a) RightPanel.tsx:240 isResizing vs isPointerResizing for the same condition R1 Gon Yes
CRF-29 Nit Author fixed (f5f777a) RightPanel.tsx:347 sidebarAutoCollapsed does not name the reason like sidebarCollapsedByDrag R1 Gon Yes
CRF-30 Nit Author fixed (f5f777a) RightPanel.test.tsx:325 Test comment states the clientWidth dependency backwards; 720 and 320 unexplained R1 Gon Yes
CRF-31 P4 Author fixed (f5f777a) RightPanel.tsx:27 Hysteresis comment says sub-pixel; 24px is a dead band R1 Leorio Yes
CRF-32 P4 Author fixed (PR description) ResizableChatsSidebarFrame.tsx:150 PR description gives an accessibility reason for w-0 + invisible; sm:hidden already had it R1 Leorio Yes
CRF-33 Note Note (body) RightPanel.tsx:444 Closed zero-width panels report isIntersecting true, so xterm keeps rendering up to 30s R1 Killua No
CRF-34 P3 Author fixed (2efe7ca) AgentsPageLayout.tsx:752 getExpandedSidebarWidth falls back to 0 (eager restore, CRF-8 loop); tests use a harness copy of the width and reducer R2 Netero Yes
CRF-35 P4 Author contested; panel closed R3 (1/1 accept) RightPanel.test.tsx:394 Remount restore test failed once in about 49 runs; cause and output unknown R2 Netero P3 Yes
CRF-36 OOS Out of scope (body) RightPanel.tsx:46 getSideBySideMaxWidth still reads lg as innerWidth < 1024 while the rest of RightPanel uses the media query R2 Netero No
CRF-37 P3 Author fixed (2efe7ca) RightPanel.tsx:364 narrowWidth collapse is restored only while the panel is open; survives close, then expands on a later panel open R2 Nami P3, Pariston P3, Mafuuu P3, Kite P3 Yes
CRF-38 P3 Author fixed (2efe7ca) ResizableChatsSidebarFrame.tsx:44 userWidth starts from the already-clamped width, so a sidebar squeezed at mount never grows back R2 Leorio Yes
CRF-39 P3 Author fixed (2efe7ca) AgentsPageLayout.tsx:708 Reset comment says route/collapse changes cancel the animation; the reset itself stops it R2 Gon P3, Leorio P4 Yes
CRF-40 P3 Author fixed (2efe7ca) RightPanel.test.tsx:441 User-collapse rule tested only against the harness reducer, which differs from the layout's; harness doc claims equivalence R2 Bisky P3, Gon P3, Leorio Nit Yes
CRF-41 P4 Author fixed (2efe7ca) RightPanel.tsx:422 width in effect deps rebuilds the observer and listener on every drag move R2 Nami P4 Yes
CRF-42 P4 Author fixed (2efe7ca) RightPanel.tsx:334 isAnimatingOpen stays true when a drag cancels the lg open transition R2 Komugi Yes
CRF-43 P4 Author fixed (2efe7ca) ResizableChatsSidebarFrame.tsx:26 viewportSlide doc omits the flex-row parent requirement and that "out" ignores isCollapsed R2 Gon Yes
CRF-44 P4 Author fixed (2efe7ca) AgentsPageLayout.tsx:126 onSidebarCollapsedByNarrowWidthChange undocumented; reads as a setter but never overrides a user collapse R2 Leorio Yes
CRF-45 P4 Author fixed (PR description) AgentsPageLayout.tsx:752 PR description says the restore check measures the rendered width; it reads the frame's width state R2 Leorio Yes
CRF-46 P4 Author fixed (PR title); title reverted with the restore in 0757b36; not re-raised R7 (Kite: description lists the width regrow) AgentsPageLayout.tsx:750 PR title names only animation; the PR also changes sidebar collapse and width behavior R2 Kite Yes
CRF-47 Nit Author fixed (2efe7ca) RightPanel.tsx:380 maybeToggleSidebar/toggleRequested no longer call a toggle R2 Gon Yes
CRF-48 Nit Author fixed (2efe7ca) index.css:755 --panel-slide-duration placed in the scrollbar :root block R2 Gon Yes
CRF-49 Nit Dropped by orchestrator ("even while collapsed" is the contract; the rest of the sentence anchors it) AgentsPageLayout.tsx:127 getExpandedSidebarWidth doc repeats the field name R2 Gon P2 No
CRF-50 P3 Author fixed (c0453ae) RightPanel.tsx:366 narrowWidth collapse is not cleared where no RightPanel renders (/agents, settings, chat not-found/error views); sidebar stays collapsed there R3 Netero P3, Hisoka P4 Yes
CRF-51 P4 Author contested; panel closed R4 (1/1 accept); reconfirmed R7 after the restore removal (1/1 accept) RightPanel.tsx:396 Expand sidebar while both panels do not fit slides the sidebar partway open, then the observer re-collapses it mid-transition R3 Nami Yes
CRF-52 P3 Author fixed (c0453ae) AgentsPageLayout.tsx:763 No test runs the layout's getExpandedSidebarWidth; a broken read (name mismatch, dropped ref) silently disables restore with CI green R3 Bisky Yes
CRF-53 P3 Author fixed (c0453ae) AgentsPageLayout.tsx:128 getExpandedSidebarWidth doc says "current width, even while collapsed" (collapsed frame renders w-0) and omits what undefined means R3 Gon P3, Leorio P4 Yes
CRF-54 P4 Author fixed (c0453ae) sidebarWidth.ts:61 loadStoredLeftSidebarWidth/loadPersistedLeftSidebarWidth differ by a synonym, not by clamping; line 36 doc omits the default fallback R3 Gon P3, Mafuuu P4, Leorio P4 Yes
CRF-55 Note Note (body) RightPanel.tsx:377 Dragging the panel narrower does not restore a narrowWidth collapse until a window/container resize or panel close R3 Nami, Komugi No
CRF-56 Nit Dropped by orchestrator (states why a close clears the collapse: it existed only to fit the panel) RightPanel.tsx:366 Close-effect comment restates the condition R3 Gon P2 No
CRF-57 Nit Dropped by orchestrator (test-file doc; names that the harness uses the layout's updater, the CRF-40 contract) RightPanel.test.tsx:66 Harness doc lists the harness body R3 Gon P2 No
CRF-58 Nit Dropped by orchestrator (round-2 review's own suggested wording for CRF-39) AgentsPageLayout.tsx:721 Reset comment's first sentence repeats the condition R3 Gon P2 No
CRF-59 Nit Dropped by orchestrator (doc requested by CRF-44; first clause tells callers that false clears) AgentsPageLayout.tsx:126 onSidebarCollapsedByNarrowWidthChange doc repeats the name R3 Gon P2 No
CRF-60 Nit Dropped by orchestrator (context field and exported function are separate API surfaces; each needs the contract) AgentsPageLayout.tsx:135 applyNarrowWidthCollapse doc repeats the name and the line 126 doc R3 Gon P2 No
CRF-61 Nit Dropped by orchestrator (a mismatch fails type checking at the viewportSlide prop, so the copies cannot drift) AgentsPageLayout.tsx:706 in/out/null slide union written in two files R3 Gon No
CRF-62 P3 Author fixed (0f9e6bb) RightPanel.tsx:367 Registration comment says an open panel keeps the collapsed sidebar from being restored; the auto-collapse effect restores it while open R4 Gon P3, Leorio P3, Mafuuu P4, Razor P4 Yes
CRF-63 P4 Author fixed (0f9e6bb) sidebarWidth.ts:72 readLeftSidebarWidth doc says the frame "renders" the expanded width while collapsed (CRF-53 wording) and omits undefined R4 Gon P3, Mafuuu P4, Leorio P4 Yes
CRF-64 P4 Author fixed (0f9e6bb) AgentsPageLayout.tsx:765 "these routes" comment lost its referent when the route condition moved into the nextSidebarViewportSlide call R4 Gon, Leorio Yes
CRF-65 P4 Author fixed (0f9e6bb) AgentsPageLayout.tsx:823 No test runs the layout's registerOpenRightPanel wiring; removing it passes all tests and disables restore on close/navigation R4 Bisky Yes
CRF-66 OOS Out of scope (body) ChatTopBar.tsx:199 Expand sidebar has no effect when sidebar and panel do not both fit (predates PR); product decision needed R4 Nami No
CRF-67 OOS Dropped by orchestrator (LEFT_SIDEBAR_WIDTH_VAR removed in 0757b36; item no longer applies) AgentsSkeletons.tsx:40 Skeleton sets and stories 542/667 read --agents-left-sidebar-width by literal, not LEFT_SIDEBAR_WIDTH_VAR R4 Robin, Gon No
CRF-68 P4 Dropped by orchestrator (a constant-only rename fails the stories that assert the literal name; Tailwind needs literal class names) sidebarWidth.ts:69 LEFT_SIDEBAR_WIDTH_VAR looks like the only definition; three Tailwind classes in the frame spell it literally R4 Gon No
CRF-69 P4 Dropped by orchestrator (name describes the counter the closure holds; not false) AgentsPageLayout.tsx:161 createOpenPanelRegistry returns a register function, not a registry R4 Gon No
CRF-70 Nit Dropped by orchestrator (round-3 review's own suggested wording for CRF-53) AgentsPageLayout.tsx:129 getExpandedSidebarWidth doc describes the caller's use of undefined R4 Gon P2 No
CRF-71 Nit Dropped by orchestrator (frame delay is documented on createOpenPanelRegistry in the same file) AgentsPageLayout.tsx:135 registerOpenRightPanel doc repeats the name and omits the frame delay R4 Gon P2 No
CRF-72 Nit Dropped by orchestrator (export doc; states the contract without reading the closure) AgentsPageLayout.tsx:156 createOpenPanelRegistry doc's first sentence describes the body R4 Gon P2 No
CRF-73 Nit Dropped by orchestrator (export doc names the rules in product terms; "after a render" describes the resulting state) AgentsPageLayout.tsx:178 nextSidebarViewportSlide doc says "after a render" and restates branches R4 Gon P2 No
CRF-74 Nit Dropped by orchestrator (answers CRF-54's request to distinguish the siblings) sidebarWidth.ts:64 loadClampedLeftSidebarWidth doc repeats the name and body R4 Gon P2 No
CRF-75 P4 Author fixed (dcd5870) AgentsPageLayout.tsx:128 Narrow-width outlet fields are optional; a producer can omit them with no type error and RightPanel silently skips auto-collapse and restore (base used the required onToggleSidebarCollapsed) R5 Knov, Pariston, Bisky, Hisoka Yes
CRF-76 Note Note (body) AgentEmbedPage.tsx:219 Embed no longer auto-collapses a sidebar it never renders; PR description does not mention it R5 Luffy, Knov No
CRF-77 OOS Out of scope (body) AgentEmbedPage.tsx:108 Embed keeps sidebar collapse state and a toggle for a sidebar it never renders R5 Knov No
CRF-78 OOS Out of scope (body) useChatDraftAttachments.test.ts "uses the default 10 MiB budget for non-Anthropic providers" failed once in a full AgentsPage run; passes alone R5 Hisoka No
CRF-79 P4 Dropped by orchestrator (unit and integration levels; the hook test survives harness or RightPanel changes) AgentsPageLayout.test.ts:1182 First useSidebarCollapseState test duplicates the RightPanel close test's path R5 Bisky No
CRF-80 Nit Dropped by orchestrator ("owns why the sidebar is collapsed" covers the user actions; accurate) AgentsPageLayout.tsx:176 useSidebarCollapseState doc names one consumer R5 Gon P2 No
CRF-81 Nit Dropped by orchestrator (round-4 review's own suggested wording for CRF-62) RightPanel.tsx:367 "Registers this panel while open." restates the effect R5 Gon P2 No
CRF-82 Nit Dropped by orchestrator (rename and wording follow the round-4 suggestion for CRF-63) sidebarWidth.ts:72 readExpandedLeftSidebarWidth doc's first sentence restates the name R5 Gon P2 No
CRF-83 Nit Dropped by orchestrator (test-file doc; accurate, misleads no caller) RightPanel.test.tsx:65 Harness doc restates the harness body R5 Gon P2 No
CRF-84 Nit Dropped by orchestrator (names mirror the outlet fields they feed; CRF-75's spread alternative would remove the mix) AgentsPageLayout.tsx:197 Hook returns verbs and one on...Change handler name R5 Gon No
CRF-85 Nit Dropped by orchestrator (two-line describe-scoped test helper; no rule broken) AgentsPageLayout.test.ts:1178 nextFrame defined twice in one test file R5 Gon No
CRF-86 P4 Author fixed (0757b36) AgentsPageLayout.tsx:180 useSidebarCollapseState and helpers live in the page module; RightPanel.test.tsx loads the whole page (import 7.25s vs 0.34s) R6 Zoro Yes
CRF-87 P4 Author fixed (0757b36) AgentEmbedPage.tsx:234 PR description and embed comment say the embed's panel no longer toggles the hidden sidebar; drag-to-edge still calls onToggleSidebarCollapsed R6 Leorio P4, Gon P2 Yes
CRF-88 P4 Dropped by orchestrator (CRF-54 offered rename or inline; author chose rename; wrapper existed at base) sidebarWidth.ts:65 loadClampedLeftSidebarWidth is a one-caller wrapper R6 Zoro No
CRF-89 P2 Open ResizableChatsSidebarFrame.tsx:43 Compiler caches maxWidth at mount; regrown or dragged sidebar stays capped and the pinned content wrapper is clipped R7 Ging-React Yes
CRF-90 P4 Open RightPanel.tsx:326 Opening straight into expanded mode sets isAnimatingOpen with no transitionend to clear it; content stays pinned after leaving expanded mode R7 Mafuuu, Komugi Yes
CRF-91 Nit Open ResizableChatsSidebarFrame.test.tsx:105 Expected widths 340 and 440 are bare literals from innerWidth - AGENTS_MAIN_PANEL_MIN_WIDTH R7 Gon P4 Yes
CRF-92 Nit Dropped by orchestrator (useState with no setter shows a mount snapshot; both uses are the next three lines) ResizableChatsSidebarFrame.tsx:39 storedWidth holds the mount-time value, not the current stored width R7 Gon No
CRF-93 P4 Dropped by orchestrator (CRF-46 raiser Kite judged no re-raise; description bullet names the regrow and the squash commit body carries it) ResizableChatsSidebarFrame.tsx:59 PR title reverted to animation only; sidebar width regrow is a behavior change R7 Leorio No
CRF-94 OOS Out of scope (body) ResizableChatsSidebarFrame.tsx:121 Before this PR, the mount-time maxWidth already capped a drag or End press after the window widened R7 Ging-React No

Contested and acknowledged

CRF-1 (P3, AgentsPageLayout.tsx:678) - sm crossing slide state has no test

  • Finding: The sm crossing slide state and its stale-slide handling had no test, so a regression in when the frame drops its route classes or clears the slide passes CI. Proposed a test that crosses (max-width: 639px) on /agents/:id and checks the slide clears on animationend and on navigating to the chat list.
  • Author defense: Added a frame test that onViewportSlideEnd fires only for the frame's own animationend; the layout-level crossing needs the full AgentsPageLayout providers, which no unit test in the directory sets up, so it is left to browser verification.
  • Panel re-raised (R2): Netero, the agent that raised it, re-raised: the render-time reset is now the only code that clears a stale "out", a regression renders invisible w-0 in place of the mobile chat list, and AgentsPageLayout.stories.tsx already renders the full layout with providers while AgentChatPage.stories.tsx:1712 crosses a breakpoint with setupMatchMedia; Pixel disables animations, so a stale "out" is deterministic in a screenshot.

CRF-2 (P3, RightPanel.tsx:316) - pinning and narrow slide-out state untested

  • Finding: isAnimatingOpen and the narrow slide-out state had no test; proposed jsdom tests firing transitionEnd/animationEnd on the panel.
  • Author defense: Both states only change class names with no callback, request, or state outcome; FE1/FE10 prohibit class-name assertions; widths were sampled in Chromium.
  • Panel closure (R2, 1/1): Netero, the agent that raised it, accepted: a regression ships as an animation glitch with no functional loss, and neither a test nor a Pixel screenshot (animations disabled) can observe these states without restructuring into a hook.

CRF-3 (P4, RightPanel.tsx:444) - closed lg class drops border-l during close

  • Finding: The divider disappears at the start of the 200ms close at lg; proposed adding border-l to the closed lg class.
  • Author defense: border-l on the closed w-0 box leaves a permanent 1px column (measured in Chromium), shifting every closed-panel layout.
  • Panel closure (R2, 1/1): Netero, the agent that raised it, accepted: a 200ms missing divider costs less than a permanent layout shift.

CRF-11 (P3, AgentsPageLayout.tsx:678) - breakpoint-crossing slides

  • Finding: The 640px/1024px crossing slides take roughly 85 production lines and carried the stale-slide and test-gap findings; proposed dropping them or fixing those findings.
  • Author defense: The PR's requester explicitly asked for the crossing slides; the stale replay, stuck slide-out, and test gap are addressed in their own threads.
  • Panel closure (R2, 1/1): Luffy, the agent that raised it, accepted the requester's stated need and verified the stale-slide paths are fixed (render-time reset in AgentsPageLayout, isNarrowSlideOut reset on reopen and on returning to lg). The remaining layout-level test gap is tracked in CRF-1.

CRF-1 (P3, AgentsPageLayout.tsx:717) - round 3 dispute

  • Finding: The sm crossing slide state and its render-time reset have no layout-level test; round 2 proposed a story that crosses (max-width: 639px) on /agents/:id and navigates to /agents.
  • Author defense (R3): A story would render desktop CSS (Storybook viewport stays desktop) with mobile JS state from setupMatchMedia, a combination users never see, and would need a play navigation step the layout stories lack; the reset is one render-time condition and the frame's slide-end contract is unit tested. Left for a human reviewer to accept or ask for more.
  • Panel re-raised (R3): Netero, the agent that raised it, re-raised with new evidence: the desktop-CSS objection applies to a story, not a unit test; the transition at AgentsPageLayout.tsx:704-724 depends only on isMobileViewport, prevIsMobileViewport, isSidebarHiddenOnMobile, isSidebarCollapsed, and the current slide, so it can move into a pure function tested with it.each in AgentsPageLayout.test.ts, the same pattern this round used for applyNarrowWidthCollapse. Rows: a stale "out" after navigating to the chat list becomes null; a stale "in" after a user collapse becomes null.

CRF-35 (P4, RightPanel.test.tsx:394) - single unexplained test failure

  • Finding: restores a sidebar it collapsed after the panel remounts failed once on a cold run at f5f777a with no failure output; proposed running both files in a loop and reporting the count.
  • Author defense: 25 of 25 loop runs passed at 2efe7ca; attributes the earlier failure to async ResizeObserver polyfill callbacks removed by the MockResizeObserver stub.
  • Panel closure (R3, 1/1): Netero, the agent that raised it, accepted: about 85 passing runs since the single failure (Netero 24 at f5f777a and 10 of 10 at 2efe7ca with all three test files, the author's 25, the orchestrator's 25); worst case is a rare CI rerun. Netero corrected the author's cause: f5f777a already stubbed ResizeObserver in this describe, and that is the commit where the test failed, so the cause remains unknown.

CRF-51 (P4, RightPanel.tsx:396) - Expand sidebar slides partway open, then re-collapses

  • Finding: When the sidebar and the panel do not both fit, "Expand sidebar" sets the collapse reason to null, and the auto-collapse observer collapses the sidebar again during the 200ms transition, so it slides partway open and back. Proposed: skip the re-collapse for a user-requested expand until the next panel open, or disable the button while the reason is narrowWidth and the restore check fails.
  • Author defense (R4): The re-collapse predates the PR (a one-frame flash before), and changing it means choosing between two product behaviors (let the expand squeeze the panel, or disable the button), which is out of scope for an animation PR; flagged for a human reviewer.
  • Panel closure (R4, 1/1): Nami, the agent that raised it, accepted: the end state matches base, and the PR improves it because the re-collapse is recorded as narrowWidth and restored once there is room or no panel is open (base left it collapsed); the only new cost is the partial slide. Nami listed the button's behavior in that width range as out of scope for a human decision (CRF-66).

CRF-51 (P4, RightPanel.tsx:396) - round 7 re-check after the restore removal

  • Finding: Same as above. 0757b36 removed the narrowWidth reason and restore that the R4 closure cited; Luffy's R7 output asked Nami to re-judge.
  • Author defense: Unchanged from R4 (predates the PR; the fix is a product choice, CRF-66).
  • Panel closure (R7, 1/1): Nami (a new agent, R7 panel; the R3/R4 outputs were listed in context.md, and the orchestrator asked it to judge the closure explicitly) accepted: the auto-collapse effect body is unchanged from base, so the end state is exactly base (collapsed, no restore); the only PR difference for that click is a partial slide of up to 200ms instead of a one-frame flash; making the button work is the CRF-66 product decision.

Round log

Round 1

Full panel, round 1. Classified multi-domain (TSX and CSS keyframes), target 9 to 12. Netero first pass: 2 P3, 1 P4, 1 Nit, 1 Note, 1 out of scope; no P0, so the panel ran. Law not run (284 effective additions). Panel: Ging-TS, Ging-React, Nami, Killua, Luffy (triggered specialists), Pariston, Mafuuu (core), Bisky (tests changed), Gon, Leorio (once-per-PR floor), Hisoka, Komugi (pool), Chopper (random wildcard from the distilled set). 13 panel reviewers, one over the target because Gon and Leorio were placed in round 1 by the floor.

Cross-check:

  • CRF-7: six reviewers converged; P2 set by Nami and Pariston (higher wins). Orchestrator verified key={agentId} at AgentChatPage.tsx:739 and the loading view's <RightPanel isOpen> at AgentChatPageView.tsx:1137.
  • CRF-8: raised from Hisoka's P3 to P2. Consequence when hit is a continuous collapse/restore oscillation until a window resize. Orchestrator verified ResizableChatsSidebarFrame reads storage only at mount and on window resize (no storage listener), which adds a second trigger: another tab saving a different width. Inferred, not reproduced.
  • CRF-10: Hisoka P3 vs Mafuuu P4 and Chopper P4; Hisoka reproduced with setItem throwing, so P3.
  • CRF-12: Komugi's Note (mutation check fails) contradicts Bisky. Orchestrator ran SIDEBAR_RESTORE_HYSTERESIS = 0: the test alone failed 8 of 8 runs; the whole RightPanel.test.tsx file passed 7 of 8 runs. Bisky's finding stands; Komugi's Note dropped as contradicted.
  • CRF-22 and CRF-23: Gon P3 vs Leorio P4/Nit with equal evidence; higher wins.
  • CRF-24 drop gate. Keep argument: AGENTS.md requires substantive comments and the line repeats the names below it. Drop reason: it states that mobile hides the sidebar on these routes, which is why the block exists; the names alone do not say that. Drop wins.
  • CRF-25 drop gate. Keep argument: the doc describes what the harness body visibly does. Drop reason: the PR only corrected a pre-existing doc to the new behavior and it states the restore purpose. Drop wins.
  • CRF-21 kept at P3. Keep argument: CRF-15 shows the raw flag does go stale, so picking the wrong name renders a stale slide-out.
  • CRF-29 kept as Nit. Keep argument: "auto" stays ambiguous wherever the flag lives after the CRF-7 fix.
  • CRF-31 vs Gon's comment audit (kept the hysteresis comment): Leorio's evidence (24px vs sub-pixel) is more specific; kept at P4.
  • Interactions: the CRF-7 fix (collapse reason in AgentsPageLayout) also resolves CRF-4, CRF-18, and affects CRF-29 and CRF-8. CRF-11 (drop crossing slides) would remove CRF-14, CRF-15, CRF-21, CRF-22, CRF-23 and parts of CRF-1, CRF-2, CRF-27.
  • Positive Notes from Nami, Bisky, Leorio, and Komugi record cleared concerns; not posted.
  • Gon cited sidebarCollapsedByDrag at line 111; it is at line 110.

2 P2, 10 P3, 11 P4, 5 Nit, 2 Note (body), 1 out of scope, 2 dropped. Reviewed against 5dde49d..1aee330.

Round 2

Restructure round: the fix commit f5f777a added three fields to the exported AgentsPageOutletContext type and a ref prop to ResizableChatsSidebarFrame, and rewrote the auto-collapse effect and the narrow slide-out state rather than patching them. Churn guard: PROCEED (25 addressed, 1 acknowledged, 2 contested, 0 silent); CRF-1 (partial fix, layout test declined) and CRF-3 (acknowledged but defended) were treated as contested so the raiser judged them. Netero reused its round-1 agent (dispute check-in for CRF-1, CRF-2, CRF-3); Law not run (463 effective additions). Panel: Ging-TS, Ging-React, Nami, Killua (specialists), Pariston, Mafuuu (core), Bisky, Gon, Leorio, Hisoka, Komugi (pool; Gon and Leorio mandatory because comments and doc comments changed), Kite (random wildcard), plus Luffy on its round-1 agent for the CRF-11 dispute check-in (not counted toward the target). 11 counted reviewers, target 9 to 12.

Dispute check-in: CRF-1 re-raised by Netero; CRF-2 and CRF-3 closed by Netero (1/1); CRF-11 closed by Luffy (1/1).

Cross-check:

  • Fixes verified by the raising reviewers: CRF-7 (Luffy, Nami, Mafuuu; Netero ran the remount test against round-1 RightPanel.tsx and it failed), CRF-8 (Hisoka, Killua), CRF-9, CRF-10, CRF-17 (Mafuuu), CRF-12 (Netero: hysteresis mutation fails 4 of 4 whole-file runs), CRF-14 and CRF-15 (Komugi, Hisoka), CRF-21, CRF-26 to CRF-30 (Gon), CRF-23, CRF-31, CRF-32 (Leorio). CRF-13's test arrived but is weakened by the fix; tracked as CRF-40. CRF-22's rewritten comment is wrong; tracked as CRF-39 (new finding, fix introduced it).
  • CRF-37: Nami, Pariston, Mafuuu, Kite at P3 (three reproduced in scratch tests); Luffy noted the same behavior and accepted it. Four specific reproductions against one acceptance; P3 stands.
  • CRF-35 downgraded P3 to P4. Keep argument: a test failed once with no code change and nobody knows why, so CI can fail on it. Downgrade reason: one failure in about 49 runs (Netero about 24, orchestrator 25 of 25 passing on both files after the panel finished), on the first run in a fresh checkout, with no failure output; Komugi measured each waitFor at 40 to 220ms of its 1000ms timeout under 2-core contention, which contradicts Netero's timeout inference from the 1118ms test duration. Downgrade wins; still posted because the author can run the loop.
  • CRF-40 merges Bisky P3 (user-collapse rule has no production-code test), Gon P3 (harness doc claims equivalence), Leorio Nit (same doc). Same cause: the harness reducer is a divergent copy of the layout's. Kept separate from CRF-34, which covers the width fallback.
  • CRF-39: Gon P3, Leorio P4; higher wins. Leorio's suggested text used.
  • CRF-41: Nami P4 vs Killua (no finding; one extra style read per frame during a drag). Kept at P4; the comment states the cost.
  • CRF-42: Komugi named two cancel paths; the narrowing path resets isAnimatingOpen because suppression closes the panel and the visualOpen block runs. Only the drag path is posted.
  • CRF-45 has no file location (PR description); anchored at AgentsPageLayout.tsx:752, the code the sentence describes.
  • CRF-46: Kite also suggested splitting the PR; only the retitle is posted (Law threshold not met).
  • CRF-49 drop gate. Keep argument: the first half of the doc repeats the field name, which AGENTS.md's substantive-comment rule targets. Drop reason: "even while collapsed" is the contract a caller needs, and the sentence reads as one unit. Drop wins.
  • Gon's CRF-43 reopens CRF-23 with new evidence (flex-row dependency omitted by the round-1 suggested wording).

5 P3 new, 7 P4 new, 2 Nit new, 1 P3 re-raised (CRF-1), 3 contested closed, 1 dropped, 1 out of scope new. Reviewed against 1aee330..f5f777a (full diff against 5dde49d).

Round 3

Restructure round: 2efe7ca changed the signature of the exported AgentsPageOutletContext.getExpandedSidebarWidth (() => number to () => number | undefined) and added exports applyNarrowWidthCollapse, SidebarCollapsedBy, and loadStoredLeftSidebarWidth. No files were added; effective additions grew 463 to 578. The commit only fixes prior findings, so a fix-round panel was also defensible; its selection (raisers of touched findings plus specialists for changed files, Gon and Leorio mandatory for changed comments) would have been the same set minus Hisoka. Churn guard: PROCEED (13 addressed, 2 contested, 0 silent). Netero reused its round-1 agent (dispute check-in for CRF-1 and CRF-35); Law not run (578 effective additions). Panel: Ging-TS, Ging-React, Nami, Killua, Luffy (specialists), Pariston, Mafuuu (core), Bisky, Gon, Leorio, Hisoka, Komugi (pool; Bisky required, Gon and Leorio mandatory on a restructure round), Kite (random wildcard from the distilled set). 12 counted plus the wildcard, target 9 to 12.

Dispute check-in: CRF-1 re-raised by Netero (new evidence: the slide transition can be a pure function tested like applyNarrowWidthCollapse, which answers the story objection). CRF-35 closed by Netero (1/1), with the correction that the ResizeObserver stub already existed at the failing commit.

Cross-check:

  • Fixes verified: CRF-34 (Netero; residual harness width constant is CRF-52), CRF-37 (Nami, Pariston, Mafuuu, Kite, Luffy; Netero's mutation of the close condition fails the new test), CRF-38 (Netero mutation, Leorio), CRF-39, CRF-43, CRF-47, CRF-48 (Gon), CRF-40 (Bisky, Gon, Leorio), CRF-41 (Nami, Killua), CRF-42 (Komugi traced every path), CRF-44, CRF-45 (Leorio), CRF-46 (Kite). Luffy replaced its round-2 acceptance of the post-close collapse with approval of the close effect.
  • CRF-50: Netero P3 (routes without agentId), Hisoka P4 (the proposed route check misses a chat's not-found and error views, AgentChatPage.tsx:717, :736). Same cause, merged; higher wins. Orchestrator confirmed no other writer clears sidebarCollapsedBy on route change and that only AgentChatPageView renders RightPanel. Base also left the auto-collapse in place (no restore existed), so this is a gap in the PR's new restore, not a regression.
  • CRF-51: Nami P4, inferred from code, not run. Orchestrator traced: the expand sets null, the effect reruns, the ResizeObserver collapses when the parent drops below chatMinWidth + MIN_WIDTH during the transition.
  • CRF-52: Bisky P3 with mutation evidence (1658 of 1658 passed with the layout's property name changed). Netero looked at the same harness constant and declined because the failure is now "never restore"; Bisky's point is that this failure is silent. Specific mutation evidence beats the decline; P3. Orchestrator found AgentsPageLayout.stories.tsx:542 and :667 read the frame's property by the same name, so a frame-side rename is caught by stories; the layout-side read and the ref are not.
  • CRF-53: Gon P3, Leorio P4, equal evidence; higher wins. Keep argument for P3 recorded: the doc is false for the collapsed case it names, and the prior CRF-8 bug was a wrong width source. Interacts with CRF-52: if the read moves to sidebarWidth.ts and undefined goes away, only the "current width" half remains.
  • CRF-54 downgrade gate (Gon P3 to P4). Keep argument: two synonym names for different contracts, and the wrong pick brings back CRF-38. Downgrade reason: the one caller where the wrong pick matters (the frame's userWidth) is pinned by grows a sidebar squeezed at mount back to the stored width, which Netero showed fails on the swap; the remaining cost is a future caller's choice. Downgrade wins; Mafuuu and Leorio also rated P4.
  • CRF-55: Nami and Komugi both judged dragging-without-restore acceptable; Note (body).
  • CRF-56 drop gate. Keep argument: AGENTS.md requires substantive comments and the condition says the same. Drop reason: the comment states why a panel close ends the collapse (it existed only to fit the panel). Drop wins.
  • CRF-57 drop gate. Keep argument: CRF-25's drop relied on the doc naming the restore purpose, which the rewrite removed. Drop reason: the doc now names that the harness uses the layout's updater rather than a copy, which is what CRF-40 required; test-file doc. Drop wins.
  • CRF-58 drop gate. Keep argument: the first sentence labels the block. Drop reason: it is the wording this review suggested in round 2; posting it would reverse our own suggestion. Drop wins.
  • CRF-59 drop gate. Keep argument: "Records or clears" repeats the name and parameter. Drop reason: CRF-44 asked for this doc and Leorio verified it; the first clause tells a caller that false clears. Drop wins.
  • CRF-60 drop gate. Keep argument: the user-collapse rule is written on both the context field and the function. Drop reason: an outlet-context consumer does not see the function, so each API surface carries its contract. Drop wins.
  • CRF-61 drop gate. Keep argument: this round named the analogous union SidebarCollapsedBy. Drop reason: a mismatch between the layout state and the viewportSlide prop fails type checking, so the copies cannot drift silently. Drop wins.
  • Gon's out-of-scope RIGHT_PANEL_SIDE_BY_SIDE_BREAKPOINT_WIDTH duplication is the same item as CRF-36; no new row.
  • Positive Notes from Luffy, Komugi, Bisky, Leorio, Kite, and Killua record cleared concerns; not posted.

3 P3 new, 2 P4 new, 1 Note (body), 1 P3 re-raised (CRF-1), 1 contested closed (CRF-35), 6 dropped. Reviewed against f5f777a..2efe7ca (full diff against 5dde49d).

Round 4

Restructure round: c0453ae added the exported createOpenPanelRegistry, nextSidebarViewportSlide, SidebarViewportSlide, LEFT_SIDEBAR_WIDTH_VAR, and readLeftSidebarWidth, added registerOpenRightPanel to the exported AgentsPageOutletContext, and renamed the exported loadPersistedLeftSidebarWidth to loadClampedLeftSidebarWidth. No files were added; effective additions grew 578 to 782. Churn guard: PROCEED (5 addressed, 1 contested, 0 silent). Netero ran as a new agent (no Netero finding contested); no findings. Law not run (782 effective additions). Panel: Ging-TS, Ging-React, Killua, Luffy (specialists), Pariston, Mafuuu (core), Bisky, Gon, Leorio, Hisoka, Komugi, Robin (pool; Bisky required, Gon and Leorio mandatory on a restructure round, Robin for the three new helpers), Razor (random wildcard from the distilled set), plus Nami on its round-3 agent for the CRF-51 dispute check-in (also the frontend specialist; not counted toward the target). 12 counted plus the wildcard, target 9 to 12.

Dispute check-in: CRF-51 closed by Nami (1/1); the underlying button behavior moved to out of scope (CRF-66).

Cross-check:

  • Fixes verified: CRF-1 (Netero: nextSidebarViewportSlide equivalent to the replaced branches; Bisky: each branch pinned by a row), CRF-50 (Netero mutation of the registration fails the close test; removing the frame wait fails the registry tests and the remount test; Nami, Hisoka, Komugi traced chat switch, loading-to-loaded swap, StrictMode, and the not-found and error views), CRF-52 (Netero, Bisky; residual layout wiring gap is CRF-65), CRF-53, CRF-54 (Leorio, Gon, Netero).
  • CRF-62: Gon P3, Leorio P3, Mafuuu P4, Razor P4, same evidence; higher wins. Consistent with CRF-39 and CRF-53 (wrong comments at P3). Gon cited line 366 (blank); the comment is at 367, which the other three cited.
  • CRF-63 downgrade gate (Gon P3 to P4). Keep argument: new code repeats the CRF-53 defect (a P3) and leaves undefined undocumented, and Gon adds that read vs load is the only name difference among three width functions. Downgrade reason: unlike CRF-53's "current width", this doc names the expanded width, which is the value callers need; the remaining inaccuracy is "renders" for "sets", and the number | undefined return with a four-line body shows the null case. Downgrade wins; Mafuuu and Leorio rated P4 with the same evidence. Gon's rename is included as an option.
  • CRF-64: Gon P4, Leorio P4. The comment was CRF-24 (dropped R1); new evidence is that its referent moved.
  • CRF-65: Bisky P4 with mutation evidence (1667 of 1667 passed with the context field removed). Same class as CRF-52 (P3 last round); Bisky rated this P4 and no reviewer argued higher. Keep argument for P3: the registry is now the only code that clears a narrowWidth collapse after close or navigation, and its layout wiring is one untested optional field. Stays P4 because the regression needs a deletion of that line, not a string drift.
  • CRF-66: Nami's out-of-scope item after accepting the CRF-51 defense.
  • CRF-67: Robin's two out-of-scope items (stories and skeleton literals) merged with the out-of-scope part of Gon's CRF-68; both predate the PR.
  • CRF-68 drop gate. Keep argument: the new constant looks like the single definition while three Tailwind classes in the same PR file spell the name, and a constant-only rename breaks sidebar width with no type error. Drop reason: AgentsPageLayout.stories.tsx:557 to :707 assert sidebarWidth() values read by the literal name, so a constant-only rename fails CI; Tailwind cannot use the constant, so the only fix is a doc sentence. Drop wins.
  • CRF-69 drop gate. Keep argument: the name says registry and both callers name the result as a function. Drop reason: the name describes the counter the closure holds, which the returned function is the only handle to; it is not false the way CRF-47's toggle names were. Drop wins.
  • CRF-70 drop gate. Keep argument: the clause documents the consumer in the producer's contract. Drop reason: it is the wording this review suggested for CRF-53 in round 3. Drop wins.
  • CRF-71 drop gate. Keep argument: the context field doc omits the frame delay that RightPanel.test.tsx:436-437 has to wait for. Drop reason: createOpenPanelRegistry, 20 lines below in the same file, documents the delay and why; "Registers an open RightPanel" names the caller, which () => () => void does not. Drop wins.
  • CRF-72 drop gate. Keep argument: the first sentence describes the counter and the frame check in the body. Drop reason: it is the contract of an exported function, stated so a caller does not need to read the closure. Drop wins.
  • CRF-73 drop gate. Keep argument: "after a render" misstates when the function runs, and two sentences restate the branches. Drop reason: the function returns the slide state that results from a render's inputs, and the sentences give the rules in product terms (sm crossing, routes that hide the sidebar) that five boolean parameters do not. Drop wins.
  • CRF-74 drop gate. Keep argument: the doc repeats the name and the one-line body. Drop reason: CRF-54 asked for the siblings to be distinguishable, and the doc names the source (stored) and the clamp reference (current viewport). Drop wins.
  • Komugi noted the frame wait relies on the old and new panels unregistering and registering in the same commit; a future Suspense or query-gated isOpen would break it. Hypothetical; the registry doc states the chat-switch assumption. Not posted.
  • Positive Notes from Nami, Luffy, Pariston, Hisoka, Komugi, Killua, and Bisky record cleared concerns; not posted.

1 P3 new, 3 P4 new, 2 out of scope new, 1 contested closed (CRF-51), 7 dropped. Reviewed against 2efe7ca..c0453ae (full diff against 5dde49d).

Round 5

Restructure round: 0f9e6bb added the exported hook useSidebarCollapseState, which now owns the layout's collapse state, and renamed the exported readLeftSidebarWidth to readExpandedLeftSidebarWidth. Every change maps to a round-4 finding, so a fix-round panel was defensible; the new exported hook moved state ownership, which is why the full panel ran. Effective additions grew 782 to 850. Churn guard: PROCEED (4 addressed, 0 contested, 0 silent). Netero ran as a new agent; no findings. Law not run. Panel: Ging-TS, Ging-React, Nami, Killua, Luffy (specialists), Pariston, Mafuuu (core), Bisky, Gon, Leorio, Hisoka, Komugi (pool; Bisky required, Gon and Leorio mandatory on a restructure round), Knov (random wildcard from the distilled set). 12 counted plus the wildcard, target 9 to 12. Robin not re-added (no in-scope findings in round 4; target reached).

Cross-check:

  • Fixes verified: CRF-62, CRF-63, CRF-64 (Gon, Mafuuu, Netero, Leorio), CRF-65 (the harness runs the production hook; Netero and Mafuuu showed that deleting registerOpenRightPanel, from the layout's outlet context fails biome lint --error-on-warnings with an unused-variable warning at line 473; the orchestrator reproduced it and restored the file).
  • CRF-75 merges four P4s. Pariston, Bisky, and Hisoka reported CRF-65 as not closed because deleting line 848 passes vitest and tsc; their "CI stays green" claim is contradicted by the lint result above, and the same holds for lines 844 to 847 (each destructured name or the readExpandedLeftSidebarWidth import becomes unused). Knov's framing survives the lint evidence: base routed auto-collapse through the required onToggleSidebarCollapsed, while the four new fields are optional, so a producer that omits them (a two-line edit in the layout, or a new producer) gets no type error and loses auto-collapse and restore silently. Keep argument for dropping considered: lint covers single-line slips and the remaining edit is deliberate. Kept at P4 because the exported type's contract weakened relative to base and the fix (required fields plus no-ops in the embed and two stories) is small. Pariston and Knov proposed required fields; Bisky and Hisoka proposed returning a typed outlet slice from the hook and spreading it. The comment gives required fields as the fix.
  • CRF-76: Luffy and Knov both inferred from code (not run) that the embed no longer auto-collapses; Note (body).
  • CRF-78: Bisky saw one unexplained failure in a full AgentsPage run; Hisoka identified useChatDraftAttachments.test.ts failing once under load and passing 17 of 17 alone. The orchestrator ran the full AgentsPage unit project 3 times at 0f9e6bb: 3 of 3 passed (1669 passed, 2 skipped). The PR does not touch that file.
  • CRF-79 drop gate. Keep argument: no mutation distinguishes the hook test from the RightPanel close test, so one is redundant. Drop reason: the hook test pins the exported hook without RightPanel, width stubs, or the harness, so it survives changes to either; the RightPanel test covers the integration. Drop wins.
  • CRF-80 drop gate. Keep argument: the doc names two of seven returned fields and one consumer. Drop reason: "owns why the sidebar is collapsed" covers the user actions, which only set that reason; the doc is accurate. Drop wins.
  • CRF-81 and CRF-82 drop gates. Keep argument: each first sentence restates the code or name. Drop reason: both follow wording and a rename this review suggested in round 4. Drop wins.
  • CRF-83 drop gate. Keep argument: CRF-57's drop reason (the doc named a contract the body did not show) no longer applies now that the body imports the hook. Drop reason: test-file doc, accurate, no caller reads it. Drop wins.
  • CRF-84 drop gate. Keep argument: one returned object mixes verb names and an outlet handler name. Drop reason: the handler-named fields pass straight into outlet fields of the same name, and CRF-75's alternative fix would make every name the outlet name. Drop wins.
  • CRF-85 drop gate. Keep argument: an identical helper is defined twice in one file by this commit. Drop reason: a two-line helper scoped to its describe, no rule broken, no reader affected. Drop wins.
  • Nami, Killua, and Komugi confirmed the hook's callbacks close over only the state setter and lint:compiler reports no failures, so the auto-collapse effect's dependencies stay stable; not posted.
  • Positive Notes from Luffy, Pariston, Mafuuu, Bisky, and Komugi record cleared concerns; not posted.

1 P4 new, 1 Note (body), 2 out of scope new, 7 dropped. Reviewed against c0453ae..0f9e6bb (full diff against 5dde49d).

Round 6

Fix round: dcd5870 (+17 -4, 4 files) applies the CRF-75 fix as the round-5 comment described it (four AgentsPageOutletContext fields made required, no-ops in the embed and two stories). That is an exported-type change, but it is the requested fix applied as written, with no new exports, rewritten functions, or files, so "a round that only fixes prior findings is not a restructure" governs. Churn guard: PROCEED (1 addressed). Netero ran as a new agent; no findings. Law not run. Panel: Knov, Pariston, Bisky, Hisoka (raised CRF-75, whose code changed), Ging-TS, Ging-React, Nami (specialists for the changed .tsx files), Gon (declarations carrying doc comments changed, and a comment was added), Leorio (new commit message and comment), Zoro (random wildcard from the distilled set). 9 panel reviewers plus the wildcard.

Cross-check:

  • CRF-75 verified by Netero, Bisky, and Hisoka: deleting registerOpenRightPanel, from the layout's outlet context now fails tsc with TS2741. Knov, Pariston, Nami, and Gon confirmed all four producers set the fields; the ?? {} and ?. in RightPanel remain for renders without an outlet, as in base.
  • CRF-76 (Note, R5) is settled: the PR description now mentions the embed change.
  • CRF-86: Zoro measured 441ms vs 6.71s import for otherwise identical one-test files. Orchestrator run: RightPanel.test.tsx reports import 7.25s; ResizableChatsSidebarFrame.test.tsx reports import 338ms. The value import from AgentsPageLayout started in round 3 (applyNarrowWidthCollapse, the CRF-40 fix) and the round-4 CRF-65 comment suggested exporting the hook from AgentsPageLayout.tsx, so this is a regression from our own suggestion; the comment says so.
  • CRF-87 merges Leorio P4 (description sentence false for drag-to-edge) and Gon P2 (the embed comment overstates the same thing and could be shorter). Orchestrator verified useResizableDrag calls onToggleSidebarCollapsed at RightPanel.tsx:148-156 and :206-211, and the embed passes its real toggle at AgentEmbedPage.tsx:232. Downgrade gate for Gon's P2: keep argument, Gon rated it P2 and the comment is new text in the fix commit. Downgrade reason: no runtime effect; the comment is literally true about the four no-op fields, and description inaccuracies were P4 before (CRF-45). P4 wins.
  • CRF-88 drop gate. Keep argument: a one-caller wrapper duplicates the composition the frame writes inline. Drop reason: the round-3 CRF-54 comment offered rename or inline and the author chose rename; the wrapper existed at base with the same body. Drop wins.
  • Netero noted the embed's no-op onSidebarCollapsedByNarrowWidthChange now lets the auto-collapse effect run in the embed (an idle observer and one no-op call); behavior unchanged. Not posted.
  • Positive Notes from Knov, Bisky, Hisoka, Nami, Ging-React, and Pariston record cleared concerns; not posted.

2 P4 new, 1 dropped. Reviewed against 0f9e6bb..dcd5870 (full diff against 5dde49d).

Round 7

Restructure round: 0757b36 (+54 -502, 10 files) removed the auto-collapsed sidebar restore instead of patching CRF-86 and CRF-87: it deleted the exports useSidebarCollapseState, createOpenPanelRegistry, applyNarrowWidthCollapse, SidebarCollapsedBy, readExpandedLeftSidebarWidth, and LEFT_SIDEBAR_WIDTH_VAR, removed four fields from the exported AgentsPageOutletContext, reverted RightPanel.test.tsx and AgentEmbedPage.tsx to base, and changed the PR title and goal back to animation only. Effective additions fell 850 to 361. Churn guard: PROCEED (2 addressed, 0 contested, 0 silent). Inventory validation: CRF-67 dropped (the constant it compared against no longer exists); CRF-55 and CRF-76 (Notes about removed code) left as recorded; the remaining dropped, Note, and out-of-scope rows still describe the current code or describe code that no longer exists. Netero ran as a new agent; no findings. Law not run (361 effective additions). Panel: Ging-TS, Ging-React, Nami, Killua, Luffy (specialists), Pariston, Mafuuu (core), Bisky, Gon, Leorio, Hisoka, Komugi (pool; Bisky required, Gon and Leorio mandatory on a restructure round), Kite (random wildcard from the distilled set). 12 counted plus the wildcard, target 9 to 12 (multi-domain: TSX and CSS keyframes, as in round 1).

CRF-51 re-check: Luffy noted the R4 closure cited the removed restore. The orchestrator asked the R7 Nami agent to judge it explicitly; Nami accepted (1/1) against the current code.

Cross-check:

  • CRF-86 and CRF-87 verified by Netero, Pariston, Leorio, and Kite: no references to the removed names remain (rg over site/src), RightPanel.test.tsx and AgentEmbedPage.tsx match base, and the description no longer mentions the embed.
  • CRF-89: Ging-React P2, with the compiled output and a jsdom reproduction. Orchestrator compiled the frame with babel-plugin-react-compiler (default options): t4 = getLeftSidebarMaxWidth() sits inside a react.memo_cache_sentinel guard. Orchestrator reproduction (temporary test, deleted): stored 600, mount at 800px, widen to 1440px gives [aria-valuenow, aria-valuemax, max-width var, width var] = ['600', '440', '440px', '600px']. Clipping is inferred from the classes (sm:max-w-(--agents-left-sidebar-max-width) and sm:overflow-hidden on the frame, sm:w-(--agents-left-sidebar-width) on the new wrapper), not run in a browser. Pariston's premise that the sidebar box never shrinks below --agents-left-sidebar-width holds only while the cached max is current. Downward test: only users whose stored width exceeds the mount-time max, or who drag after widening, see it, and a reload or a narrower drag clears it. Upward: the clipped strip holds the right side of every chat row, and base showed no clipping (children filled the capped frame). P2 (wrong but survivable) stands. The base cap for drags and End presses is CRF-94, out of scope; the CRF-89 fix also covers it.
  • CRF-90: Mafuuu P4 and Komugi P4, both with a jsdom reproduction; Komugi's Playwright run fired no transition events for position:absolute; inset:0 to width:min(...). Orchestrator confirmed AgentChatPageView.tsx:376-379 gates expansion off instead of resetting it, so a reopen restores it. Same root cause as CRF-16 and CRF-42 (the flag is cleared only by a width transitionend); the fix sets it only for side-by-side opens.
  • CRF-91 downgrade gate (Gon P4 to Nit). Keep argument: two expected widths do not name which of three clamps produced them, a change to AGENTS_MAIN_PANEL_MIN_WIDTH breaks them with no pointer, and the same file derives expectations from LEFT_SIDEBAR_DEFAULT_WIDTH. Downgrade reason: the tests fail loudly with innerWidth stubbed on the line above; no coverage or behavior risk; divergence from the file's own pattern is the Nit definition. Downgrade wins.
  • CRF-92 drop gate. Keep argument: after the first drag storedWidth no longer matches storage, and a later edit could use it in the resize handler and regrow to the mount-time width. Drop reason: const [storedWidth] = useState(...) with no setter reads as a mount snapshot, and both uses are the next three lines. Drop wins.
  • CRF-93 drop gate. Keep argument: CRF-46 was posted and fixed for this, the author reverted the title, and git log --oneline and the generated changelog show only the title. Drop reason: Kite, who raised CRF-46, judged no re-raise because the description lists the regrow as its own bullet; squash commits on main carry the PR body (verified on 2c1e888 and 93a00bd); Leorio's stated consequence (bisect skipping a commit by title) does not follow, since bisect tests every candidate. Drop wins. CRF-46's status records the revert.
  • Contradiction: Leorio (re-raise CRF-46) vs Kite (no re-raise); resolved in CRF-93.
  • Positive Notes from Luffy (removal matches the requester's ask), Bisky (mutations fail the remaining tests), Leorio (comments accurate), Killua (no unbounded work; CRF-33 still describes the code), and Kite record cleared concerns; not posted.

1 P2, 1 P4, 1 Nit new, 1 out of scope new, 2 dropped, 1 closure reconfirmed (CRF-51). Reviewed against dcd5870..0757b36 (full diff against 5dde49d).

About deep-review

CRF = Coder Review Finding (P0-P4, Nit, Note)

Reviewer Focus
Bisky tests
Chopper ops/errors
Churn-guard change verification
Ging language modernization
Gon naming
Hisoka edge cases
Killua perf
Kite change integrity
Knov contracts
Knuckle SQL
Komugi flake/determinism
Kurapika security
Law decomposition
Leorio docs
Luffy product
Mafu-san process
Mafuuu contracts
Melody dispatch/pairing
Meruem structural
Nami frontend
Netero mechanical checks
Pariston premise testing
Pen-botter product gaps
Razor verification
Robin duplication
Ryosuke Go arch
Takumi concurrency
Zoro shape

🤖 Managed by Coder Agents.

@tracyjohnsonux
tracyjohnsonux marked this pull request as ready for review September 27, 2026 01:52
@tracyjohnsonux
tracyjohnsonux requested a review from a team as a code owner September 27, 2026 01:52

@coder-agents-review coder-agents-review 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.

This PR animates the agents sidebar and right panel on toggle and across the sm/lg breakpoints, and restores a sidebar the right panel auto-collapsed. Findings: 2 P2, 10 P3, 11 P4, 5 Nit.

Moving the collapse reason into AgentsPageLayout (the remount finding on RightPanel.tsx:347) also removes the mirroring effect and the redundant ref write.

Out of scope (needs a ticket or explicit acceptance by a human):

  • site/src/pages/AgentsPage/components/RightPanel/RightPanel.tsx:263: the resize handler clamps width with Math.min(prev, ...) and the effect at line 354 saves it, so narrowing the window permanently overwrites the saved right panel width, the same squeezed-width problem this PR fixes for the left sidebar.

Notes:

  • ResizableChatsSidebarFrame.tsx:134: --panel-width and --agents-left-sidebar-width hold the same value on the frame; AgentsPageLayout.stories.tsx reads the second one.
  • RightPanel.tsx:444: at lg, content inside the closed zero-width panel reports isIntersecting: true to IntersectionObserver (checked in headless Chromium; display: none reported false), so xterm keeps rendering output until TerminalPanel detaches it after 30s.

🤖 This review was automatically generated with Coder Agents.

Comment thread site/src/pages/AgentsPage/components/RightPanel/RightPanel.tsx Outdated
Comment thread site/src/pages/AgentsPage/components/RightPanel/RightPanel.tsx Outdated
Comment thread site/src/pages/AgentsPage/components/RightPanel/RightPanel.tsx Outdated
Comment thread site/src/pages/AgentsPage/components/ChatsSidebar/ResizableChatsSidebarFrame.tsx Outdated
Comment thread site/src/pages/AgentsPage/AgentsPageLayout.tsx Outdated
Comment thread site/src/pages/AgentsPage/components/RightPanel/RightPanel.tsx Outdated
Comment thread site/src/pages/AgentsPage/components/RightPanel/RightPanel.tsx Outdated
Comment thread site/src/pages/AgentsPage/components/RightPanel/RightPanel.tsx Outdated
Comment thread site/src/pages/AgentsPage/components/RightPanel/RightPanel.tsx Outdated
Comment thread site/src/pages/AgentsPage/components/RightPanel/RightPanel.test.tsx Outdated
Track why the sidebar collapsed in AgentsPageLayout so a right panel
remount no longer forgets it collapsed the sidebar, and measure the
sidebar's rendered width when deciding to restore it. Restoring now also
leaves room for the panel's current width.

Keep the user's sidebar width in memory so failed storage writes survive
window resizes, clear stale breakpoint slides during render, and share one
slide duration between transitions and keyframes.
@tracyjohnsonux

Copy link
Copy Markdown
Contributor Author

/coder-agents-review

@coder-agents-review coder-agents-review 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.

This round reviews f5f777a, which addresses the round-1 findings. New findings: 5 P3, 7 P4, 2 Nit. The layout-level crossing test is still requested on its thread.

Verified fixed: the collapse reason now lives in AgentsPageLayout, the restore check reads the frame's width and leaves room for the panel's width, the sidebar keeps the user's width in memory, the auto-collapse tests stub ResizeObserver, and stale slides are reset during render. The defenses for the pinning and slide-out tests, the closed-panel border, and the crossing slides are accepted.

Two findings come from round-1 fixes: the in-memory width ref starts from an already-clamped width, and the rewritten reset comment names a cause that no longer applies.

Out of scope (needs a ticket or explicit acceptance by a human):

  • site/src/pages/AgentsPage/components/RightPanel/RightPanel.tsx:46: getSideBySideMaxWidth still reads lg as innerWidth < 1024 while the rest of RightPanel now uses belowLgViewportMediaQuery, so changing one makes the width clamp and the side-by-side switch disagree.
  • site/src/pages/AgentsPage/components/RightPanel/RightPanel.tsx:268: still open from round 1; the resize clamp overwrites the saved right panel width.

🤖 This review was automatically generated with Coder Agents.

Comment thread site/src/pages/AgentsPage/components/RightPanel/RightPanel.tsx
Comment thread site/src/pages/AgentsPage/components/ChatsSidebar/ResizableChatsSidebarFrame.tsx Outdated
Comment thread site/src/pages/AgentsPage/AgentsPageLayout.tsx Outdated
Comment thread site/src/pages/AgentsPage/components/RightPanel/RightPanel.test.tsx Outdated
Comment thread site/src/pages/AgentsPage/AgentsPageLayout.tsx Outdated
Comment thread site/src/pages/AgentsPage/AgentsPageLayout.tsx Outdated
Comment thread site/src/pages/AgentsPage/AgentsPageLayout.tsx Outdated
Comment thread site/src/pages/AgentsPage/AgentsPageLayout.tsx Outdated
Comment thread site/src/pages/AgentsPage/components/RightPanel/RightPanel.tsx Outdated
Comment thread site/src/index.css
Restore a sidebar collapsed for the right panel when the panel closes,
seed the sidebar's in-memory width from the unclamped stored value, and
skip the restore check when the sidebar width is unknown. Move the
collapse-reason updater into an exported function that the layout and
tests share.
@tracyjohnsonux tracyjohnsonux changed the title feat(site/src): animate agents sidebar and panel collapse feat(site/src): animate agents panels and restore auto-collapsed sidebar Sep 27, 2026
@tracyjohnsonux

Copy link
Copy Markdown
Contributor Author

/coder-agents-review

@coder-agents-review coder-agents-review 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.

This round reviews 2efe7ca, which addresses the round-2 findings. New findings: 3 P3, 2 P4. The layout-level crossing test is re-raised on its thread with a unit-test approach.

Verified fixed: closing the panel restores a sidebar it collapsed, the frame seeds its in-memory width from the unclamped stored width, the harness uses the layout's applyNarrowWidthCollapse, the width getter returns undefined instead of 0, the auto-collapse effect no longer depends on the panel width, and a drag clears isAnimatingOpen. The defense for the single remount-test failure is accepted, with a correction on its thread.

If the crossing test is not added, a human reviewer needs to accept that gap.

Out of scope (needs a ticket or explicit acceptance by a human):

  • site/src/pages/AgentsPage/components/RightPanel/RightPanel.tsx:46: getSideBySideMaxWidth still reads lg through RIGHT_PANEL_SIDE_BY_SIDE_BREAKPOINT_WIDTH = 1024 while the rest of RightPanel uses belowLgViewportMediaQuery, so changing one makes the width clamp and the side-by-side switch disagree.
  • site/src/pages/AgentsPage/components/RightPanel/RightPanel.tsx:263: the resize clamp overwrites the saved right panel width.

Notes:

  • site/src/pages/AgentsPage/components/RightPanel/RightPanel.tsx:377: dragging the panel narrower does not restore a sidebar collapsed to fit it; the restore check runs again only on a window or container resize, a sidebar or expand change, or a panel close.

🤖 This review was automatically generated with Coder Agents.

Comment thread site/src/pages/AgentsPage/components/RightPanel/RightPanel.tsx Outdated
Comment thread site/src/pages/AgentsPage/components/RightPanel/RightPanel.tsx Outdated
Comment thread site/src/pages/AgentsPage/AgentsPageLayout.tsx Outdated
Comment thread site/src/pages/AgentsPage/AgentsPageLayout.tsx Outdated
Comment thread site/src/pages/AgentsPage/components/ChatsSidebar/sidebarWidth.ts Outdated
Track open right panels in AgentsPageLayout so a narrow-width sidebar
collapse clears whenever no open panel remains, including on routes that
never mount one. Move the viewport slide transition into a pure function,
share the sidebar width CSS variable between the frame and its reader,
and rename the clamped width loader.
@tracyjohnsonux

Copy link
Copy Markdown
Contributor Author

/coder-agents-review

@coder-agents-review coder-agents-review 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.

This round reviews c0453ae, which addresses the round-3 findings. New findings: 1 P3, 3 P4.

Verified fixed: the crossing slide logic is a pure function with an it.each table, open panels register with the layout so a narrow-width collapse clears on close and on every view without a panel (chat switches excluded), the width read shares a constant with the frame and has a frame test, and the doc and naming fixes landed. The defense for the expand-button re-collapse is accepted; the button's behavior in that width range is listed below for a human decision.

Out of scope (needs a ticket or explicit acceptance by a human):

  • site/src/pages/AgentsPage/components/ChatTopBar.tsx:199: when the sidebar and the right panel do not both fit, the auto-collapse effect overrides "Expand sidebar", so the button has no effect in that width range (also true before this PR); the choice is between letting the expand squeeze the panel and disabling the button.
  • site/src/pages/AgentsPage/components/AgentsSkeletons.tsx:40: sets --agents-left-sidebar-width by literal, and AgentsPageLayout.stories.tsx:542 and :667 read it by literal, so renaming LEFT_SIDEBAR_WIDTH_VAR leaves them on the old name.
  • site/src/pages/AgentsPage/components/RightPanel/RightPanel.tsx:46: getSideBySideMaxWidth still reads lg through RIGHT_PANEL_SIDE_BY_SIDE_BREAKPOINT_WIDTH = 1024 while the rest of RightPanel uses belowLgViewportMediaQuery, so changing one makes the width clamp and the side-by-side switch disagree.
  • site/src/pages/AgentsPage/components/RightPanel/RightPanel.tsx:263: the resize clamp overwrites the saved right panel width.

🤖 This review was automatically generated with Coder Agents.

Comment thread site/src/pages/AgentsPage/components/RightPanel/RightPanel.tsx Outdated
Comment thread site/src/pages/AgentsPage/components/ChatsSidebar/sidebarWidth.ts Outdated
Comment thread site/src/pages/AgentsPage/AgentsPageLayout.tsx Outdated
Comment thread site/src/pages/AgentsPage/AgentsPageLayout.tsx Outdated
@tracyjohnsonux

Copy link
Copy Markdown
Contributor Author

/coder-agents-review

@coder-agents-review coder-agents-review 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.

This round reviews 0f9e6bb, which addresses the round-4 findings. New findings: 1 P4.

Verified fixed: the registration comment, the readExpandedLeftSidebarWidth rename and doc, the routes comment, and the shared useSidebarCollapseState hook, which the RightPanel harness now runs. Deleting only the registerOpenRightPanel line from the layout's outlet context now fails biome lint --error-on-warnings (unused variable), so the round-4 scenario is caught.

Out of scope (needs a ticket or explicit acceptance by a human):

  • site/src/pages/AgentsPage/AgentEmbedPage.tsx:108: the embed keeps sidebar collapse state and a toggle for a sidebar it never renders, so ChatTopBar shows "Expand sidebar" whenever anything sets that state.
  • site/src/pages/AgentsPage/hooks/useChatDraftAttachments.test.ts: "uses the default 10 MiB budget for non-Anthropic providers" failed once in a full src/pages/AgentsPage run and passed 17 of 17 alone, so it can fail CI on unrelated PRs.
  • site/src/pages/AgentsPage/components/ChatTopBar.tsx:199: when the sidebar and the right panel do not both fit, "Expand sidebar" has no effect (also true before this PR); the choice is between letting the expand squeeze the panel and disabling the button.
  • site/src/pages/AgentsPage/components/AgentsSkeletons.tsx:40: sets --agents-left-sidebar-width by literal, and AgentsPageLayout.stories.tsx:542 and :667 read it by literal, so renaming LEFT_SIDEBAR_WIDTH_VAR leaves them on the old name.
  • site/src/pages/AgentsPage/components/RightPanel/RightPanel.tsx:46: getSideBySideMaxWidth reads lg through RIGHT_PANEL_SIDE_BY_SIDE_BREAKPOINT_WIDTH = 1024 while the rest of RightPanel uses belowLgViewportMediaQuery, so changing one makes the width clamp and the side-by-side switch disagree.
  • site/src/pages/AgentsPage/components/RightPanel/RightPanel.tsx:263: the resize clamp overwrites the saved right panel width.

Notes:

  • site/src/pages/AgentsPage/AgentEmbedPage.tsx:219: the embed does not pass onSidebarCollapsedByNarrowWidthChange, so its right panel no longer collapses the sidebar the embed never renders; before this PR a narrow embed could show "Expand sidebar" (inferred from the code, not run). The PR description does not mention this change.

🤖 This review was automatically generated with Coder Agents.

Comment thread site/src/pages/AgentsPage/AgentsPageLayout.tsx Outdated
@tracyjohnsonux

Copy link
Copy Markdown
Contributor Author

/coder-agents-review

@coder-agents-review coder-agents-review 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.

This round reviews dcd5870, which makes the four narrow-width outlet fields required. New findings: 2 P4.

Verified fixed: omitting any of the four fields from a producer now fails tsc (TS2741), and the layout, the embed, and both story contexts set them. The embed change is now in the PR description.

Out of scope (needs a ticket or explicit acceptance by a human):

  • site/src/pages/AgentsPage/AgentEmbedPage.tsx:108: the embed keeps sidebar collapse state and a toggle for a sidebar it never renders, so ChatTopBar shows "Expand sidebar" whenever anything sets that state.
  • site/src/pages/AgentsPage/hooks/useChatDraftAttachments.test.ts: "uses the default 10 MiB budget for non-Anthropic providers" failed once in a full src/pages/AgentsPage run and passed 17 of 17 alone, so it can fail CI on unrelated PRs.
  • site/src/pages/AgentsPage/components/ChatTopBar.tsx:199: when the sidebar and the right panel do not both fit, "Expand sidebar" has no effect (also true before this PR); the choice is between letting the expand squeeze the panel and disabling the button.
  • site/src/pages/AgentsPage/components/AgentsSkeletons.tsx:40: sets --agents-left-sidebar-width by literal, and AgentsPageLayout.stories.tsx:542 and :667 read it by literal, so renaming LEFT_SIDEBAR_WIDTH_VAR leaves them on the old name.
  • site/src/pages/AgentsPage/components/RightPanel/RightPanel.tsx:46: getSideBySideMaxWidth reads lg through RIGHT_PANEL_SIDE_BY_SIDE_BREAKPOINT_WIDTH = 1024 while the rest of RightPanel uses belowLgViewportMediaQuery, so changing one makes the width clamp and the side-by-side switch disagree.
  • site/src/pages/AgentsPage/components/RightPanel/RightPanel.tsx:263: the resize clamp overwrites the saved right panel width.

🤖 This review was automatically generated with Coder Agents.

Comment thread site/src/pages/AgentsPage/AgentsPageLayout.tsx Outdated
Comment thread site/src/pages/AgentsPage/AgentEmbedPage.tsx Outdated
@tracyjohnsonux tracyjohnsonux changed the title feat(site/src): animate agents panels and restore auto-collapsed sidebar feat(site/src): animate agents panels Sep 27, 2026
@tracyjohnsonux

Copy link
Copy Markdown
Contributor Author

/coder-agents-review

@coder-agents-review coder-agents-review 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.

This round reviews 0757b36, which removes the auto-collapsed sidebar restore and leaves the panel animations and the sidebar width regrow. New findings: 1 P2, 1 P4, 1 Nit.

Resolved by the removal: RightPanel.test.tsx no longer imports the page module, and the description no longer makes the embed claim.

Out of scope (needs a ticket or explicit acceptance by a human):

  • site/src/pages/AgentsPage/AgentEmbedPage.tsx:108: the embed keeps sidebar collapse state and a toggle for a sidebar it never renders, so ChatTopBar shows "Expand sidebar" whenever anything sets that state.
  • site/src/pages/AgentsPage/hooks/useChatDraftAttachments.test.ts: "uses the default 10 MiB budget for non-Anthropic providers" failed once in a full src/pages/AgentsPage run and passed 17 of 17 alone, so it can fail CI on unrelated PRs.
  • site/src/pages/AgentsPage/components/ChatTopBar.tsx:199: when the sidebar and the right panel do not both fit, "Expand sidebar" has no lasting effect: the sidebar slides partway open and the right panel's auto-collapse closes it again (before this PR it flashed for one frame); the choice is between letting the expand squeeze the panel and disabling the button.
  • site/src/pages/AgentsPage/components/RightPanel/RightPanel.tsx:43: getSideBySideMaxWidth reads lg through RIGHT_PANEL_SIDE_BY_SIDE_BREAKPOINT_WIDTH = 1024 while the rest of RightPanel uses belowLgViewportMediaQuery, so changing one makes the width clamp and the side-by-side switch disagree.
  • site/src/pages/AgentsPage/components/RightPanel/RightPanel.tsx:263: the resize clamp overwrites the saved right panel width, so the panel stays at the squeezed width after the window widens.
  • site/src/pages/AgentsPage/components/ChatsSidebar/ResizableChatsSidebarFrame.tsx:121: before this PR too, the mount-time maximum capped the rendered sidebar after the window widened, so a drag or End press past it moved aria-valuenow but not the sidebar edge.

🤖 This review was automatically generated with Coder Agents.

const [width, setWidth] = useState(() => clampLeftSidebarWidth(storedWidth));
// The width the user chose, kept in memory because storage writes can fail.
const userWidth = useRef(storedWidth);
const maxWidth = getLeftSidebarMaxWidth();

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.

P2 [CRF-89] The React Compiler computes maxWidth once per mount, so a sidebar that grows back after the window widens stays capped at the mount-time maximum, and the new fixed-width content wrapper is clipped. (Ging-React)

getLeftSidebarMaxWidth() has no reactive inputs, so the compiled component evaluates it once inside a react.memo_cache_sentinel guard, and --agents-left-sidebar-max-width and aria-valuemax never change after mount. With a stored width of 600, mounting at 800px and widening to 1440px gives aria-valuenow 600 (so grows a sidebar squeezed at mount back to the stored width passes) but aria-valuemax 440 and a 440px max-width variable, so sm:max-w-(--agents-left-sidebar-max-width) holds the frame at 440px and sm:overflow-hidden cuts off the right 160px of the 600px wrapper until reload (from the classes, not run in a browser); a drag past 440px after the widen ends the same way, while before this PR the children filled the capped frame. Keep maxWidth in state with useState(getLeftSidebarMaxWidth), set it in the resize handler next to setWidth, and assert aria-valuemax in that test.

🤖

const [prevIsSideBySide, setPrevIsSideBySide] = useState(isSideBySide);
if (visualOpen !== prevVisualOpen) {
setPrevVisualOpen(visualOpen);
setIsAnimatingOpen(visualOpen && !isPointerResizing && !isBelowLg);

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.

P4 [CRF-90] Opening the panel straight into expanded mode sets isAnimatingOpen, and nothing clears it, so after the user leaves expanded mode the content stays pinned to --panel-width until the next close or drag. (Mafuuu, Komugi)

AgentChatPageView.tsx:376-379 keeps expansion through a close and restores it with the panel, so a reopen renders visualOpen and visualExpanded together; the expanded panel has no transition class, and leaving expanded mode changes width from auto, which does not transition, so no transitionend arrives (Chromium fired no transition events for that change). Rendering (isOpen, isExpanded) as (false, false), (true, true), then (true, false) in jsdom leaves lg:w-(--panel-width) on the content wrapper, and expanding during the 200ms open slide should end the same way (inferred). The pinned content is 1px wider than the bordered box and loses its left column (items-end), and more whenever the box renders narrower than the width state. Set the flag only for side-by-side opens (setIsAnimatingOpen(isSideBySide && !isPointerResizing) at line 326) and clear it whenever isSideBySide turns false.

🤖

const handle = renderHandle();

vi.stubGlobal("innerWidth", 700);
fireEvent(window, new Event("resize"));

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.

Nit [CRF-91] The expected widths "340" here and "440" at line 118 are bare literals for innerWidth - AGENTS_MAIN_PANEL_MIN_WIDTH. (Gon)

getLeftSidebarMaxWidth() takes the smallest of 660, 70% of the window, and the window minus 360, and the test does not say which applies at 700px and 800px, while the tests above derive their expectations from LEFT_SIDEBAR_DEFAULT_WIDTH. Import AGENTS_MAIN_PANEL_MIN_WIDTH and write String(700 - AGENTS_MAIN_PANEL_MIN_WIDTH) and String(800 - AGENTS_MAIN_PANEL_MIN_WIDTH).

🤖

This branch has not been deployed

No deployments
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.

2 participants