Skip to content

next/prev-comment keybinding jumps backward when selection is on a non-annotated hunk #235

@aldevv

Description

@aldevv

Summary

With agent notes attached, the next/prev-comment keybinding (and the equivalent hunk session navigate --next-comment / --prev-comment API) appears to "stop working" — pressing it teleports the user backward to the first comment instead of advancing to the next one. Repros in vanilla 0.10.0 once the user has scrolled (or otherwise moved selection) off any of the annotated hunks.

Repro

  1. hunk diff <range> on a multi-file diff
  2. Attach agent notes to a few hunks
  3. Press next-comment a couple of times to advance
  4. Scroll a little (or press next-hunk) so the centered selection lands on a non-annotated hunk
  5. Press next-comment again → viewport jumps back to the first comment instead of advancing to the next one

It's reliably reproducible because viewport-centered selection (findViewportCenteredHunkTargetonViewportCenteredHunkChange) keeps shifting selectedHunkIndex to whichever hunk is centered as the user scrolls. That hunk is frequently not annotated, so the next press of next/prev-comment hits the no-exact-match fallback path.

Root cause

src/ui/lib/hunks.ts:findNextHunkCursor:

const currentIndex = cursors.findIndex(
  (cursor) => cursor.fileId === currentFileId && cursor.hunkIndex === currentHunkIndex,
);
const nextIndex =
  currentIndex >= 0
    ? Math.min(Math.max(currentIndex + delta, 0), cursors.length - 1)
    : delta >= 0
      ? 0
      : cursors.length - 1;

When (currentFileId, currentHunkIndex) isn't an exact match in the (filtered) cursor list — which is the common case for annotated-cursor navigation, since the user's selection lives on the full hunk stream — the fallback unconditionally returns the first or last cursor regardless of where the user actually is. Often that's backwards from their position.

Suggested fix

Resolve the relative position from the cursor list itself instead of falling back to first/last:

  • Files appear in stream order in the cursor list, and within a file hunkIndex is ascending.
  • The first appearance of each file in the cursor list gives a stable per-file stream rank.
  • For a non-matching (currentFileId, currentHunkIndex):
    • delta ≥ 0 → first cursor whose stream rank is strictly greater than the current position.
    • delta < 0 → last cursor whose stream rank is strictly less than the current position.
  • Only fall back to start/end when the current file has no cursors at all (file with no annotations) or when the search exhausts the list.

The existing test cases at src/ui/lib/hunks.test.ts:160-170 happen to coincide with the "first/last cursor" answer because they exercise a single-cursor list, so they don't catch the regression — worth adding regression tests for non-annotated current with a multi-cursor list.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions