Skip to content

feat: show linked issues#1852

Open
janburzinski wants to merge 4 commits intogeneralaction:mainfrom
janburzinski:jan/gen-970-show-when-an-issue-is-already-being-worked-on-by-an-agent
Open

feat: show linked issues#1852
janburzinski wants to merge 4 commits intogeneralaction:mainfrom
janburzinski:jan/gen-970-show-when-an-issue-is-already-being-worked-on-by-an-agent

Conversation

@janburzinski
Copy link
Copy Markdown
Collaborator

show which tasks are already linked to an agent to avoid doing stuff double :D

image

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 1, 2026

Greptile Summary

This PR adds "already linked" indicators to both issue selector components so users can see at a glance which issues are already attached to another agent task, preventing duplicate linking. Issues are surfaced via a new getLinkedIssueMap helper that reads MobX-observable task state and is consumed inside observer-wrapped components.

  • P1 — invisible cursor on search/provider change in InlineIssueSelector: handleQueryChange and handleProviderChange reset highlightedIndex to 0 without checking whether the item at index 0 is linked. If it is, the highlight is suppressed (isHighlighted && !isLinked guard) and Enter silently does nothing, leaving the user with no visual cue about cursor position until they press ArrowDown.

Confidence Score: 4/5

Safe to merge with the initial highlighted-index bug addressed first.

One P1 issue: setHighlightedIndex(0) in handleQueryChange/handleProviderChange can place the cursor on a disabled linked item, making it invisible and silently blocking Enter. All other logic is sound.

src/renderer/features/tasks/components/issue-selector/inline-issue-selector.tsx — handleQueryChange and handleProviderChange need the same skip-linked logic used by ArrowDown.

Important Files Changed

Filename Overview
src/renderer/features/tasks/components/issue-selector/use-linked-issue-urls.ts New helper that iterates observable task state to build an issue-URL → task-info map; correctly excludes archived tasks and the current task via excludeTaskId.
src/renderer/features/tasks/components/issue-selector/inline-issue-selector.tsx Wraps component in observer and adds linked-issue awareness; arrow-key navigation correctly skips linked items, but setHighlightedIndex(0) in handleQueryChange/handleProviderChange can silently place the cursor on a disabled item.
src/renderer/features/tasks/components/issue-selector/issue-selector.tsx Adds LinkedToTaskBadge and IssueRow linkedTo prop; IssueSelector wraps with observer and disables ComboboxItems for already-linked issues.
src/renderer/features/tasks/task-titlebar.tsx Passes excludeTaskId={taskId} to IssueSelector so the current task's own issue isn't shown as already-linked.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[User opens issue selector] --> B[getLinkedIssueMap called\ninside observer component]
    B --> C{projectId\nprovided?}
    C -- No --> D[Return empty Map]
    C -- Yes --> E[Iterate taskManager.tasks]
    E --> F{isRegistered &\nnot archived &\nnot excludeTaskId?}
    F -- Yes --> G[Add issue URL →\nLinkedIssueInfo to Map]
    F -- No --> E
    G --> H[Map passed to IssueRow]
    H --> I{issue.url in Map?}
    I -- Yes --> J[Render LinkedToTaskBadge\n+ disable item]
    I -- No --> K[Render normal selectable item]
    J --> L[ArrowDown/Up skips\ndisabled items]
    K --> L
Loading

Comments Outside Diff (1)

  1. src/renderer/features/tasks/components/issue-selector/inline-issue-selector.tsx, line 66-73 (link)

    P1 Initial cursor position ignores linked items after query/provider change

    handleQueryChange (line 71) and handleProviderChange (line 82) both call setHighlightedIndex(0) unconditionally. If the first result in the new list is a linked issue, the cursor lands on a disabled item: the highlight is invisible (isHighlighted && !isSelected && !isLinked blocks the background), and pressing Enter silently does nothing. The ArrowDown fix in this PR only helps once the user already knows to press it. The initialisation step should forward-scan for the first non-linked index, the same way ArrowDown does.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: src/renderer/features/tasks/components/issue-selector/inline-issue-selector.tsx
    Line: 66-73
    
    Comment:
    **Initial cursor position ignores linked items after query/provider change**
    
    `handleQueryChange` (line 71) and `handleProviderChange` (line 82) both call `setHighlightedIndex(0)` unconditionally. If the first result in the new list is a linked issue, the cursor lands on a disabled item: the highlight is invisible (`isHighlighted && !isSelected && !isLinked` blocks the background), and pressing Enter silently does nothing. The ArrowDown fix in this PR only helps once the user already knows to press it. The initialisation step should forward-scan for the first non-linked index, the same way ArrowDown does.
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
src/renderer/features/tasks/components/issue-selector/inline-issue-selector.tsx:66-73
**Initial cursor position ignores linked items after query/provider change**

`handleQueryChange` (line 71) and `handleProviderChange` (line 82) both call `setHighlightedIndex(0)` unconditionally. If the first result in the new list is a linked issue, the cursor lands on a disabled item: the highlight is invisible (`isHighlighted && !isSelected && !isLinked` blocks the background), and pressing Enter silently does nothing. The ArrowDown fix in this PR only helps once the user already knows to press it. The initialisation step should forward-scan for the first non-linked index, the same way ArrowDown does.

Reviews (2): Last reviewed commit: "fix: skip linked issues in keyboard nav,..." | Re-trigger Greptile

disabled,
excludeTaskId,
}: InlineIssueSelectorProps) {
const linkedIssueMap = getLinkedIssueMap(projectId, excludeTaskId);
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 New Map instance on every render invalidates useCallback

getLinkedIssueMap returns a freshly constructed Map on every render. Because linkedIssueMap is included in the dependency array of handleKeyDown (line 114), the callback is recreated on every render — negating the memoization benefit. Consider stabilising the reference via useMemo(() => getLinkedIssueMap(projectId, excludeTaskId), [projectId, excludeTaskId]), so the map only rebuilds when the underlying observable data actually changes.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/renderer/features/tasks/components/issue-selector/inline-issue-selector.tsx
Line: 37

Comment:
**New `Map` instance on every render invalidates `useCallback`**

`getLinkedIssueMap` returns a freshly constructed `Map` on every render. Because `linkedIssueMap` is included in the dependency array of `handleKeyDown` (line 114), the callback is recreated on every render — negating the memoization benefit. Consider stabilising the reference via `useMemo(() => getLinkedIssueMap(projectId, excludeTaskId), [projectId, excludeTaskId])`, so the map only rebuilds when the underlying observable data actually changes.

How can I resolve this? If you propose a fix, please make it concise.

Address PR review:
- ArrowDown/ArrowUp now skip past linked (disabled) issues so the
  highlight is always visible and Enter never silently no-ops.
- Hold linkedIssueMap in a ref and drop it from handleKeyDown deps so
  the callback is no longer recreated every render. (useMemo here would
  break MobX reactivity — observables wouldn't be re-read on cached
  renders, leaving the map stale.)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@janburzinski
Copy link
Copy Markdown
Collaborator Author

@greptile review

@arnestrickmann
Copy link
Copy Markdown
Contributor

are issues that are already linked to a task disabled in this implementation?

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