Skip to content

Multi-PR Lane Links -> Primary - #1046

Merged
arul28 merged 2 commits into
mainfrom
ade/multi-pr-lane-links
Aug 6, 2026
Merged

Multi-PR Lane Links -> Primary#1046
arul28 merged 2 commits into
mainfrom
ade/multi-pr-lane-links

Conversation

@arul28

@arul28 arul28 commented Aug 6, 2026

Copy link
Copy Markdown
Owner

ADE   Open in ADE  ·  ade/multi-pr-lane-links branch  ·  PR #1046

Summary by CodeRabbit

  • New Features

    • Pull requests can now be linked to specific chat sessions.
    • Chat views show only relevant linked pull requests, with support for multiple PRs.
    • Lane badges and work areas display PR counts, statuses, CI/review indicators, and attention levels.
    • PR lists support opening individual PRs or viewing all lane PRs.
  • Bug Fixes

    • Previous-branch pull requests remain available as lane history after branch changes.
    • PR merge actions now affect only explicitly linked chat sessions.
    • PR and chat associations are cleaned up when records are removed.

@vercel

vercel Bot commented Aug 6, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
ade Ignored Ignored Preview Aug 6, 2026 10:03am

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@arul28, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 31 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: e2740e9e-dad5-432f-8c71-d725c5a0cf10

📥 Commits

Reviewing files that changed from the base of the PR and between b13e188 and 2017847.

📒 Files selected for processing (13)
  • apps/desktop/src/main/services/prs/prService.ts
  • apps/desktop/src/renderer/components/chat/AgentChatPane.tsx
  • apps/desktop/src/renderer/components/chat/ChatGitToolbar.test.tsx
  • apps/desktop/src/renderer/components/chat/ChatGitToolbar.tsx
  • apps/desktop/src/renderer/components/chat/ChatPrPane.tsx
  • apps/desktop/src/renderer/components/lanes/LanePrBadgePopover.tsx
  • apps/desktop/src/renderer/components/lanes/LanesPage.tsx
  • apps/desktop/src/renderer/components/terminals/LanePrBadge.test.tsx
  • apps/desktop/src/renderer/components/terminals/LanePrBadge.tsx
  • apps/desktop/src/renderer/components/terminals/useLanePrs.test.ts
  • apps/desktop/src/renderer/components/terminals/useLanePrs.ts
  • apps/desktop/src/renderer/lib/prChatScope.ts
  • apps/ios/ADE/Services/Database.swift
📝 Walkthrough

Walkthrough

Changes

Chat-linked pull requests and lane history

Layer / File(s) Summary
Contracts and association persistence
apps/desktop/src/shared/types/prs.ts, apps/desktop/src/main/services/state/kvDb.ts, apps/ios/ADE/Resources/DatabaseBootstrap.sql, apps/ios/ADE/Services/*, apps/ade-cli/src/services/sync/*
PR arguments and database synchronization now support pull_request_chat_sessions associations.
PR linking and lane history
apps/desktop/src/main/services/prs/prService.ts, apps/desktop/src/main/services/lanes/laneService.ts, apps/desktop/src/main/services/prs/*test.ts
PR creation and linking persist session associations. Branch changes retain previous PR rows as lane history.
Chat-scoped PR routing
apps/desktop/src/main/services/prs/prChatCards.ts, apps/desktop/src/main/services/prs/prMergeAutoSettlementService.ts, apps/desktop/src/renderer/components/chat/*, apps/desktop/src/renderer/lib/prChatScope.ts
Chat cards, merge settlement, panes, and toolbars use explicit session links and support multiple linked PRs.
Multi-PR lane presentation
apps/desktop/src/renderer/components/lanes/*, apps/desktop/src/renderer/components/terminals/*, apps/desktop/src/renderer/lib/lanePrBadge.ts
Lane selectors and badges include active and historical PRs, attention ranking, PR lists, and lane-filtered navigation.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

  • arul28/ADE#240: Directly overlaps PR service, chat toolbar, lane selection, and multi-session PR behavior.
  • arul28/ADE#284: Shares lane PR selection and badge logic.
  • arul28/ADE#988: Shares retained historical PR rows and cleanup behavior.

Suggested labels: desktop, ios, docs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.69% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: support for multiple pull-request links per lane and primary PR handling.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ade/multi-pr-lane-links

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
apps/desktop/src/renderer/components/chat/ChatGitToolbar.tsx (1)

234-247: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Both PR surfaces subscribe to the whole lanes array to read one lane. Each component needs lane metadata for selectPrimaryLanePr, and each added useAppStore((s) => s.lanes) plus a lanes entry in its refresh callback dependency list. The store replaces that array on every lane refresh and cross-machine merge, so both refresh callbacks change identity on a timer, which resets PR state and re-creates the prs.onEvent subscriptions. Both files already solve this class of problem for runtimePin by keying on runtimePinKey and reading the object through a ref.

  • apps/desktop/src/renderer/components/chat/ChatGitToolbar.tsx#L234-L247: select the single lane by laneId, read it in refreshPr through a ref, and replace lanes in the dependency list with a primitive key built from the lane fields selectPrimaryLanePr uses (laneType, branchRef, baseRef).
  • apps/desktop/src/renderer/components/chat/ChatPrPane.tsx#L444-L519: apply the same change to refresh, so the reconcile subscription at lines 555-580 and the prs-updated subscription at lines 593-610 keep the stable-dependency guarantee their comments describe.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/desktop/src/renderer/components/chat/ChatGitToolbar.tsx` around lines
234 - 247, In apps/desktop/src/renderer/components/chat/ChatGitToolbar.tsx lines
234-247, replace the whole-lanes subscription with the single lane selected by
laneId, read that lane through a ref inside refreshPr, and replace lanes in its
dependencies with a primitive key containing laneType, branchRef, and baseRef.
Apply the same change to refresh in
apps/desktop/src/renderer/components/chat/ChatPrPane.tsx lines 444-519; the
later reconcile and prs-updated subscriptions require no direct changes and must
retain stable dependencies.
apps/desktop/src/main/services/prs/prChatCards.ts (1)

543-549: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Correct the failure count denominator after the fan-out change.

results now holds sessions.length * cards.length entries, but the message still divides by cards.length. With 2 sessions and 1 card, a total failure reports "Failed to emit 2 of 1 PR chat cards."

🐛 Proposed fix
   const failures = results.filter((result) => result.status === "rejected");
   if (failures.length > 0) {
     throw new AggregateError(
       failures.map((failure) => failure.reason),
-      `Failed to emit ${failures.length} of ${cards.length} PR chat cards.`,
+      `Failed to emit ${failures.length} of ${results.length} PR chat cards.`,
     );
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/desktop/src/main/services/prs/prChatCards.ts` around lines 543 - 549,
Update the AggregateError message in the fan-out result handling to use the
total number of emitted card-session operations, based on results.length, as the
denominator instead of cards.length. Keep the existing failure collection and
error propagation unchanged.
🧹 Nitpick comments (7)
apps/desktop/src/renderer/components/chat/ChatPrInlineCreator.test.tsx (1)

182-182: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a case that asserts sessionId is omitted when no chat owns the creator.

The implementation uses a conditional spread, so the key must be absent rather than null for non-chat surfaces such as the Work grid. Only the positive case is covered. Add a second case that renders without sessionId and asserts expect(createFromLane.mock.calls[0][0]).not.toHaveProperty("sessionId").

As per coding guidelines: "Record a named regression test or exact alternate verification for every accepted correctness finding."

Also applies to: 197-197

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/desktop/src/renderer/components/chat/ChatPrInlineCreator.test.tsx` at
line 182, Add a named regression test alongside the existing positive case in
the ChatPrInlineCreator tests that renders without sessionId, triggers creation,
and asserts the createFromLane payload does not have a sessionId property.
Preserve the existing session-owned case and use the exact absence assertion
requested.

Source: Coding guidelines

apps/desktop/src/main/services/prs/prMergeAutoSettlementService.ts (1)

96-98: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract the linked-chat-id normalization into one shared helper.

The same normalization now exists here and in prChatCards.ts (lines 199-201), and prChatScope.ts performs an unnormalized includes check on the same field. Three copies of one contract will drift. A single exported helper, for example normalizeLinkedChatSessionIds(pr.chatSessionIds), keeps trimming rules identical everywhere.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/desktop/src/main/services/prs/prMergeAutoSettlementService.ts` around
lines 96 - 98, Extract the chat-session ID normalization currently used in the
auto-settlement flow into one exported helper, such as
normalizeLinkedChatSessionIds, and reuse it in prMergeAutoSettlementService,
prChatCards, and prChatScope. Ensure the helper preserves the existing null-safe
conversion, trimming, and empty-value filtering, and update prChatScope’s
membership check to use the normalized IDs.
apps/desktop/src/renderer/components/chat/ChatGitToolbar.test.tsx (1)

140-149: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add component-level coverage for the new sessionId prop.

This test exercises the pure helper only. The changed behavior in ChatGitToolbar.tsx is broader: refreshPr now calls window.ade.prs.listAll, filters detached rows, applies selectPrsForChat, and picks a primary PR with selectPrimaryLanePr; the prs-updated handler also filters by chat membership. None of that is covered.

Add a render test that mounts ChatGitToolbar with sessionId set and a mocked window.ade.prs.listAll returning two lane PRs with different chatSessionIds, then assert that the pill shows the linked PR and that the +N counter appears only when more than one scoped PR exists.

As per coding guidelines: "Record a named regression test or exact alternate verification for every accepted correctness finding."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/desktop/src/renderer/components/chat/ChatGitToolbar.test.tsx` around
lines 140 - 149, Add a component-level regression test for ChatGitToolbar that
renders it with sessionId, mocks window.ade.prs.listAll to return lane PRs
assigned to different chatSessionIds, and verifies only the current chat’s PR
appears in the pill. Also verify the +N counter is absent for one scoped PR and
appears when multiple PRs belong to the session, covering refreshPr and
prs-updated filtering behavior.

Source: Coding guidelines

apps/desktop/src/renderer/components/lanes/LanePrBadgePopover.tsx (1)

101-105: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove the duplicated attention reduce.

Lines 102-104 repeat the reduce from lines 96-98 with the same inputs, so aggregate always equals primaryPr. Derive the color from primaryPr.

♻️ Proposed refactor
   if (allPrs.length > 1) {
-    const aggregate = allPrs.reduce((best, candidate) => (
-      lanePrAttentionRank(candidate) > lanePrAttentionRank(best) ? candidate : best
-    ), allPrs[0]!);
-    const aggregateColor = lanePrAttentionColor(lanePrAttention(aggregate));
+    const aggregateColor = lanePrAttentionColor(lanePrAttention(primaryPr));
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/desktop/src/renderer/components/lanes/LanePrBadgePopover.tsx` around
lines 101 - 105, Remove the redundant reduce in the allPrs aggregation block and
derive aggregateColor directly from primaryPr using lanePrAttentionColor and
lanePrAttention.
apps/desktop/src/renderer/components/lanes/lanePageModel.ts (1)

448-474: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Compute each GitHub match once.

Line 451 and line 469 run the same laneGithubPrs.find((candidate) => githubPrMatchesAdePr(mappedPr, candidate)) lookup for every mapped PR. One pass can build both the tags and the matched-id set.

♻️ Proposed refactor
-  const mappedTags = mappedPrs.map((mappedPr) => {
-    const githubPr = laneGithubPrs.find((candidate) => githubPrMatchesAdePr(mappedPr, candidate)) ?? null;
+  const githubPrByMappedPrId = new Map<string, GitHubPrListItem>();
+  for (const mappedPr of mappedPrs) {
+    const match = laneGithubPrs.find((candidate) => githubPrMatchesAdePr(mappedPr, candidate));
+    if (match) githubPrByMappedPrId.set(mappedPr.id, match);
+  }
+  const mappedTags = mappedPrs.map((mappedPr) => {
+    const githubPr = githubPrByMappedPrId.get(mappedPr.id) ?? null;
     // The PrSummary carries diff/checks/reviews; the matching GitHub item carries
     // labels/author. Merge so the popover card has the richest data available.
@@
-  const mappedGithubKeys = new Set(mappedPrs.map((mappedPr) => (
-    laneGithubPrs.find((candidate) => githubPrMatchesAdePr(mappedPr, candidate))?.id
-  )).filter((id): id is string => Boolean(id)));
+  const mappedGithubKeys = new Set([...githubPrByMappedPrId.values()].map((item) => item.id));
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/desktop/src/renderer/components/lanes/lanePageModel.ts` around lines 448
- 474, Refactor the mapped PR processing around mappedTags and mappedGithubKeys
to perform each laneGithubPrs.find match only once per mappedPr. Reuse the
computed GitHub match both when constructing the mapped tag and when collecting
matched IDs, while preserving the existing terminal-update, preference, merge,
and unmapped-tag behavior.
apps/desktop/src/renderer/components/lanes/LanesPage.test.ts (1)

382-399: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a test for the combined multi-tag selection.

These tests cover selectLanePrs and lanePrRole. The new selectLaneTabPrTags behavior is not covered: it merges mapped ADE PRs with unmatched GitHub PRs, assigns laneRole, and orders results with compareLaneTabPrTags. Add a case with one active mapped PR, one previous mapped PR, and one GitHub-only PR, then assert the returned order and each laneRole.

As per path instructions: "Record a named regression test or exact alternate verification for every accepted correctness finding."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/desktop/src/renderer/components/lanes/LanesPage.test.ts` around lines
382 - 399, Extend the existing lane PR test coverage with a regression case for
selectLaneTabPrTags using one active mapped PR, one previous mapped PR, and one
unmatched GitHub PR. Assert the merged result order from compareLaneTabPrTags
and verify each returned entry has the expected laneRole, including the
GitHub-only entry.

Source: Path instructions

apps/desktop/src/renderer/components/lanes/LanesPage.tsx (1)

644-659: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Derive the primary map from the tags map.

Both memos call selectLaneTabPrTags(lane, lanePrTags, laneGithubPrTags) with identical arguments, so the full per-lane selection runs twice for every lane on each PR data change. Compute the tags map first, then take the first entry of each list.

♻️ Proposed refactor
-  const lanePrByLaneId = useMemo(() => {
-    const map = new Map<string, LaneTabPrTag>();
-    for (const lane of sortedLanes) {
-      const pr = selectLaneTabPrTags(lane, lanePrTags, laneGithubPrTags)[0] ?? null;
-      if (pr) map.set(lane.id, pr);
-    }
-    return map;
-  }, [sortedLanes, lanePrTags, laneGithubPrTags]);
   const lanePrTagsByLaneId = useMemo(() => {
     const map = new Map<string, LaneTabPrTag[]>();
     for (const lane of sortedLanes) {
       const tags = selectLaneTabPrTags(lane, lanePrTags, laneGithubPrTags);
       if (tags.length > 0) map.set(lane.id, tags);
     }
     return map;
   }, [sortedLanes, lanePrTags, laneGithubPrTags]);
+  const lanePrByLaneId = useMemo(() => {
+    const map = new Map<string, LaneTabPrTag>();
+    for (const [laneId, tags] of lanePrTagsByLaneId) {
+      const pr = tags[0];
+      if (pr) map.set(laneId, pr);
+    }
+    return map;
+  }, [lanePrTagsByLaneId]);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/desktop/src/renderer/components/lanes/LanesPage.tsx` around lines 644 -
659, Update the lanePrByLaneId and lanePrTagsByLaneId memoization flow so
selectLaneTabPrTags is invoked only while building lanePrTagsByLaneId; derive
lanePrByLaneId from that tags map by selecting each lane’s first tag, preserving
the existing omission of lanes without tags and the memoization dependencies.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/desktop/src/renderer/components/chat/AgentChatPane.tsx`:
- Line 11801: Update the PR scoping prop at the shown call site to use
renderedSessionId instead of selectedSessionId, and apply the same replacement
to the ChatPrPane sessionId flow that reaches ChatPrInlineCreator and
prs.createFromLane. Preserve selectedSessionId for unrelated internal state
usage while ensuring header, PR pane, and PR creation target the currently
rendered chat during prop-driven switches.

In `@apps/desktop/src/renderer/components/chat/ChatPrPane.tsx`:
- Line 444: Replace the full lanes-array subscription used by refresh with a
selector for the current lane’s stable identifying fields, such as laneId and
projectRoot, following the existing runtimePinKey pattern. Update refresh and
its dependency inputs so lane-array refreshes do not change refresh identity,
preserving the event subscriptions’ stable-dependency invariant while retaining
updates when the selected lane’s stable fields change.

In `@apps/desktop/src/renderer/components/lanes/LanesPage.tsx`:
- Around line 887-890: Bound the PR IDs used by the refresh flow around
matchedPrIds and refreshPrsCoalesced to active PRs plus a small historical
window, rather than every ID returned by selectLanePrs across sortedLanesRef.
Preserve deduplication and the existing early return when no IDs remain, and
apply the cap either before calling refreshPrsCoalesced or within that
coalescer.

In `@apps/desktop/src/renderer/components/terminals/LanePrBadge.tsx`:
- Around line 166-175: Update the status container in LanePrBadge.tsx to use a
semantic status element with an accessible name that includes the specific CI
and review values, such as “CI failing; review changes requested,” rather than
exposing only the generic label. In LanePrBadge.test.tsx, add a named regression
test that queries and verifies this specific combined accessible name.

In `@apps/desktop/src/renderer/components/terminals/useLanePrs.ts`:
- Around line 74-80: Update the GitHub PR lookup in the mapped PR transformation
within useLanePrs to match by both repository identity (owner/repo) and
githubPrNumber, consistent with the identity logic used later in the function.
Preserve the existing stack fallback chain and null behavior after selecting the
repository-aware match.

In `@apps/ios/ADE/Services/Database.swift`:
- Around line 2982-2996: Remove the duplicate pull_request_chat_sessions table
creation and its three indexes from ensureHydrationProjectionColumns, keeping
the canonical definitions in ensurePullRequestProjectionTables. Leave the
worker_agents linear_identity_json column migration unchanged.

---

Outside diff comments:
In `@apps/desktop/src/main/services/prs/prChatCards.ts`:
- Around line 543-549: Update the AggregateError message in the fan-out result
handling to use the total number of emitted card-session operations, based on
results.length, as the denominator instead of cards.length. Keep the existing
failure collection and error propagation unchanged.

In `@apps/desktop/src/renderer/components/chat/ChatGitToolbar.tsx`:
- Around line 234-247: In
apps/desktop/src/renderer/components/chat/ChatGitToolbar.tsx lines 234-247,
replace the whole-lanes subscription with the single lane selected by laneId,
read that lane through a ref inside refreshPr, and replace lanes in its
dependencies with a primitive key containing laneType, branchRef, and baseRef.
Apply the same change to refresh in
apps/desktop/src/renderer/components/chat/ChatPrPane.tsx lines 444-519; the
later reconcile and prs-updated subscriptions require no direct changes and must
retain stable dependencies.

---

Nitpick comments:
In `@apps/desktop/src/main/services/prs/prMergeAutoSettlementService.ts`:
- Around line 96-98: Extract the chat-session ID normalization currently used in
the auto-settlement flow into one exported helper, such as
normalizeLinkedChatSessionIds, and reuse it in prMergeAutoSettlementService,
prChatCards, and prChatScope. Ensure the helper preserves the existing null-safe
conversion, trimming, and empty-value filtering, and update prChatScope’s
membership check to use the normalized IDs.

In `@apps/desktop/src/renderer/components/chat/ChatGitToolbar.test.tsx`:
- Around line 140-149: Add a component-level regression test for ChatGitToolbar
that renders it with sessionId, mocks window.ade.prs.listAll to return lane PRs
assigned to different chatSessionIds, and verifies only the current chat’s PR
appears in the pill. Also verify the +N counter is absent for one scoped PR and
appears when multiple PRs belong to the session, covering refreshPr and
prs-updated filtering behavior.

In `@apps/desktop/src/renderer/components/chat/ChatPrInlineCreator.test.tsx`:
- Line 182: Add a named regression test alongside the existing positive case in
the ChatPrInlineCreator tests that renders without sessionId, triggers creation,
and asserts the createFromLane payload does not have a sessionId property.
Preserve the existing session-owned case and use the exact absence assertion
requested.

In `@apps/desktop/src/renderer/components/lanes/lanePageModel.ts`:
- Around line 448-474: Refactor the mapped PR processing around mappedTags and
mappedGithubKeys to perform each laneGithubPrs.find match only once per
mappedPr. Reuse the computed GitHub match both when constructing the mapped tag
and when collecting matched IDs, while preserving the existing terminal-update,
preference, merge, and unmapped-tag behavior.

In `@apps/desktop/src/renderer/components/lanes/LanePrBadgePopover.tsx`:
- Around line 101-105: Remove the redundant reduce in the allPrs aggregation
block and derive aggregateColor directly from primaryPr using
lanePrAttentionColor and lanePrAttention.

In `@apps/desktop/src/renderer/components/lanes/LanesPage.test.ts`:
- Around line 382-399: Extend the existing lane PR test coverage with a
regression case for selectLaneTabPrTags using one active mapped PR, one previous
mapped PR, and one unmatched GitHub PR. Assert the merged result order from
compareLaneTabPrTags and verify each returned entry has the expected laneRole,
including the GitHub-only entry.

In `@apps/desktop/src/renderer/components/lanes/LanesPage.tsx`:
- Around line 644-659: Update the lanePrByLaneId and lanePrTagsByLaneId
memoization flow so selectLaneTabPrTags is invoked only while building
lanePrTagsByLaneId; derive lanePrByLaneId from that tags map by selecting each
lane’s first tag, preserving the existing omission of lanes without tags and the
memoization dependencies.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 516457d1-b59f-4c18-83cb-b86e5d65ba2e

📥 Commits

Reviewing files that changed from the base of the PR and between 9fcd792 and b13e188.

⛔ Files ignored due to path filters (4)
  • docs/features/lanes/README.md is excluded by !docs/**
  • docs/features/pull-requests/README.md is excluded by !docs/**
  • docs/features/sync-and-multi-device/README.md is excluded by !docs/**
  • docs/features/sync-and-multi-device/ios-companion.md is excluded by !docs/**
📒 Files selected for processing (38)
  • apps/ade-cli/src/services/sync/syncRemoteCommandService.ts
  • apps/desktop/src/main/services/lanes/laneService.test.ts
  • apps/desktop/src/main/services/lanes/laneService.ts
  • apps/desktop/src/main/services/prs/prAsync.test.ts
  • apps/desktop/src/main/services/prs/prChatCards.test.ts
  • apps/desktop/src/main/services/prs/prChatCards.ts
  • apps/desktop/src/main/services/prs/prMergeAutoSettlementService.ts
  • apps/desktop/src/main/services/prs/prService.test.ts
  • apps/desktop/src/main/services/prs/prService.ts
  • apps/desktop/src/main/services/prs/pullRequestRowCleanup.ts
  • apps/desktop/src/main/services/state/kvDb.ts
  • apps/desktop/src/main/services/sync/syncRemoteCommandService.test.ts
  • apps/desktop/src/renderer/components/chat/AgentChatPane.tsx
  • apps/desktop/src/renderer/components/chat/ChatGitToolbar.test.tsx
  • apps/desktop/src/renderer/components/chat/ChatGitToolbar.tsx
  • apps/desktop/src/renderer/components/chat/ChatPrInlineCreator.test.tsx
  • apps/desktop/src/renderer/components/chat/ChatPrInlineCreator.tsx
  • apps/desktop/src/renderer/components/chat/ChatPrPane.tsx
  • apps/desktop/src/renderer/components/lanes/LanePrBadgePopover.tsx
  • apps/desktop/src/renderer/components/lanes/LaneWorkPane.tsx
  • apps/desktop/src/renderer/components/lanes/LanesPage.test.ts
  • apps/desktop/src/renderer/components/lanes/LanesPage.tsx
  • apps/desktop/src/renderer/components/lanes/lanePageModel.ts
  • apps/desktop/src/renderer/components/terminals/CliSessionWorkSurfaceHeader.tsx
  • apps/desktop/src/renderer/components/terminals/LanePrBadge.test.tsx
  • apps/desktop/src/renderer/components/terminals/LanePrBadge.tsx
  • apps/desktop/src/renderer/components/terminals/SessionCard.tsx
  • apps/desktop/src/renderer/components/terminals/SessionListPane.tsx
  • apps/desktop/src/renderer/components/terminals/useLanePrs.test.ts
  • apps/desktop/src/renderer/components/terminals/useLanePrs.ts
  • apps/desktop/src/renderer/components/work/WorkSurfaceHeader.tsx
  • apps/desktop/src/renderer/lib/lanePrBadge.test.ts
  • apps/desktop/src/renderer/lib/lanePrBadge.ts
  • apps/desktop/src/renderer/lib/prChatScope.ts
  • apps/desktop/src/shared/types/prs.ts
  • apps/ios/ADE/Resources/DatabaseBootstrap.sql
  • apps/ios/ADE/Services/Database.swift
  • apps/ios/ADE/Services/SyncService.swift

Comment thread apps/desktop/src/renderer/components/chat/AgentChatPane.tsx Outdated
Comment thread apps/desktop/src/renderer/components/chat/ChatPrPane.tsx Outdated
Comment thread apps/desktop/src/renderer/components/lanes/LanesPage.tsx
Comment thread apps/desktop/src/renderer/components/terminals/LanePrBadge.tsx Outdated
Comment thread apps/desktop/src/renderer/components/terminals/useLanePrs.ts
Comment thread apps/ios/ADE/Services/Database.swift Outdated
@arul28
arul28 merged commit c019038 into main Aug 6, 2026
66 of 68 checks passed
@arul28
arul28 deleted the ade/multi-pr-lane-links branch August 6, 2026 10:22
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.

1 participant