Skip to content

fix: approveIssue() uses wrong data source in board/swimlanes view#35

Merged
marcus merged 1 commit intomarcus:mainfrom
yashas-salankimatt:approve-in-review-fix
Feb 19, 2026
Merged

fix: approveIssue() uses wrong data source in board/swimlanes view#35
marcus merged 1 commit intomarcus:mainfrom
yashas-salankimatt:approve-in-review-fix

Conversation

@yashas-salankimatt
Copy link
Contributor

Summary

  • approveIssue() approved the wrong task when using the board swimlanes view, especially visible in the "in review" column
  • Root cause: the function directly indexed into m.TaskListRows using m.Cursor[PanelTaskList], which is only valid in the flat list view — in swimlanes mode, the actual selection lives in m.BoardMode.SwimlaneRows / m.BoardMode.SwimlaneCursor
  • Fixed by replacing the manual cursor/row lookup with m.SelectedIssueID(), which already correctly handles all three view modes (list, kanban, swimlanes)

Root Cause

Every other action function in actions.go (submitToReview, confirmDelete, reopenIssue, etc.) uses the view-mode-aware SelectedIssueID() helper to resolve the selected task. approveIssue() was the only function that bypassed this helper and manually indexed into m.TaskListRows — it did this to access row.Category for a CategoryReviewable guard check.

When the swimlanes view was added, SelectedIssueID() was updated to handle the new data structures, but approveIssue() was missed because it didn't go through that code path. The stale m.TaskListRows array has a completely different ordering than the swimlane rows, so the cursor position mapped to the wrong task.

Why the CategoryReviewable guard removal is safe

The old code checked row.Category != CategoryReviewable before proceeding. This guard is redundant because approveIssue() already has two equivalent checks downstream:

  1. State machine validation (IsValidTransition(issue.Status, StatusClosed)) — only in_review issues can transition to closed via approval
  2. Self-review prevention (issue.ImplementerSession == m.SessionID) — blocks approving your own work

These two checks enforce the exact same constraints that CategoryReviewable was guarding.

Test plan

  • go build ./... compiles clean
  • go test ./pkg/monitor/... all tests pass
  • Manual test: open swimlanes view with multiple in_review tasks, approve each one — verify the correct task is approved

🤖 Generated with Claude Code

approveIssue() was directly indexing into m.TaskListRows using
m.Cursor[PanelTaskList], which is only valid in the flat list view.
In board swimlanes mode, the actual selection lives in
m.BoardMode.SwimlaneRows with m.BoardMode.SwimlaneCursor, and in
kanban mode it lives in m.BoardMode.Issues with m.BoardMode.Cursor.

This caused the wrong task to be approved when using the swimlanes
view, particularly visible in the "in review" column where the
stale index mapped to an entirely different task.

The fix replaces the manual cursor/row lookup with
m.SelectedIssueID(), which already handles all three view modes
correctly. The old CategoryReviewable guard was redundant — the
state machine validation and self-review check already enforce
the same constraints.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@yashas-salankimatt yashas-salankimatt deleted the approve-in-review-fix branch February 17, 2026 13:21
@yashas-salankimatt yashas-salankimatt restored the approve-in-review-fix branch February 18, 2026 19:43
@marcus marcus merged commit 1bb794f into marcus:main Feb 19, 2026
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