Refreshing Lanes Tabs#328
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
📝 WalkthroughWalkthroughThis PR extends PR creation with both GitHub and ADE deep-link URLs, refactors agent skills root discovery to support multiple sources, improves project/lane switching with warm cache restoration and state preservation, and adds lanes routing with project transition UI. ChangesPR Deep-Link URLs for Handoff
Agent Skills Discovery and Organization
Project Switching and Warm State Restoration
App Routing, Lanes Surface, and Project Transition UI
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Possibly related PRs
Suggested labels
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
|
|
@copilot review but do not make fixes |
|
Capy auto-review is paused for this organization because the monthly auto-review limit has been reached. Increase the limit or turn it off in billing settings to resume automatic reviews. |
There was a problem hiding this comment.
PR Review
Scope: 60 file(s), +1596 / −220
Verdict: Minor issues
This PR makes Lanes tab state stick across tab switches and project changes (keep-alive routing, warm-tab lane cache, explicit rootPath on local-runtime IPC during switches), and broadens agent-skill / PR-deeplink discovery across desktop, CLI, TUI, and iOS. The race fixes and tests look solid; the main risks are prompt/env bloat from unbounded skill discovery.
⚡ Performance
[Medium] All discovered skills are injected into every Claude session startup prompt
File: apps/desktop/src/main/services/chat/agentChatService.ts:L14426-L14451
Issue: The prior MAX_INJECTED_PROJECT_SKILLS cap and “N more hidden” note were removed. Every discovered skill (name, description, and full filePath) is now appended to the Claude Code preset systemPrompt on session start.
Impact: Repos with many .agents/.ade/.claude/.codex skills can add thousands of tokens to every new Work chat cold start, increasing latency and cost with no user-visible benefit until a skill is actually relevant.
Fix: Restore a bounded slice for prompt injection (keep full discovery for slash-command UI), e.g. reintroduce MAX_INJECTED_PROJECT_SKILLS and the hidden-count line for overflow.
[Medium] Prompt/env skill-root lists are no longer capped
File: apps/desktop/src/shared/agentSkillRoots.ts:L48-L59 and L153-L158
Issue: getAdeAgentSkillRootsForPrompt now returns the full getAgentSkillRootCandidates set. That walks up to 25 ancestors × four roots (.claude, .agents, .ade, .codex) per cwd, plus home and bundled fallbacks—often dozens to 100+ directories in monorepos.
Impact: ADE_AGENT_SKILLS_DIRS and the “Agent skill roots for this session” guidance string can grow very large for CLI launches and CTO/mission prompts, slowing startup and making env blocks harder for runtimes to parse.
Fix: Keep broad discovery for filesystem scanning, but cap prompt/env emission (the previous .slice(0, 4) on prompt roots was a reasonable default).
Notes
- Good patterns: Lanes keep-alive passes
active={active && isLanesRoute}so existingif (!active) returnguards inLanesPageshould keep background lane/PR polling off while parked;useLaneWorkSessionsref-scoping fixes mid-flight lane/project switches; preloadrootPath+ binding rollback on failedswitchToPathis well tested. - Security: No exploitable issues found in the diff; explicit
rootPathon local-runtime IPC is appropriate for trusted Electron preload during project transitions (not a web attacker boundary). - Verification gap: iOS HTTPS
ade.app/openrouting was reviewed from code/tests only; not exercised on a device in this run.
Sent by Cursor Automation: BUGBOT in Versic
9901b85 to
6ff3dbc
Compare
|
@copilot review but do not make fixes |
Reviewed |
|
@copilot review but do not make fixes |
6724ead to
03e26f1
Compare
|
@copilot review but do not make fixes |
|
@copilot review but do not make fixes |
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (7)
apps/desktop/src/main/services/ai/tools/ctoOperatorTools.ts (1)
192-199: ⚡ Quick winConsolidate duplicated ADE PR deeplink builder.
Line 192 duplicates the same
buildAdePrUrllogic already added inapps/desktop/src/main/services/ai/tools/workflowTools.ts. Extracting this into a shared helper avoids contract drift.🤖 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/ai/tools/ctoOperatorTools.ts` around lines 192 - 199, The buildAdePrUrl function duplicates logic already present in workflowTools.ts; extract the deeplink construction into a shared helper (e.g., a new exported function like createAdePrDeeplink or reuse an existing shared module) and replace both buildAdePrUrl implementations to call that helper; locate usages of buildAdePrUrl in ctoOperatorTools.ts and workflowTools.ts and update imports to reference the new shared helper, ensuring the helper takes a PrSummary (or the same repoOwner/repoName/prNumber fields) and internally calls buildDeeplink.apps/desktop/src/main/services/ipc/runtimeBridge.test.ts (1)
197-239: ⚡ Quick winAdd matching explicit-
rootPathtests for sync/events handlers.This new test protects
IPC.localRuntimeCallAction, but the same override logic was added forIPC.localRuntimeCallSyncandIPC.localRuntimeStreamEvents. Adding parallel assertions would close a high-risk regression gap for project-switch routing.🤖 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/ipc/runtimeBridge.test.ts` around lines 197 - 239, Add tests mirroring the existing IPC.localRuntimeCallAction case for the other two handlers: IPC.localRuntimeCallSync and IPC.localRuntimeStreamEvents. Reuse the same registerRuntimeBridge setup (including localRuntimeConnectionPool and getWindowSession with binding "/old-repo"), invoke ipcHandlers.get(IPC.localRuntimeCallSync) and ipcHandlers.get(IPC.localRuntimeStreamEvents) with an eventForSender and a payload containing rootPath: "/new-repo", then assert the returned values resolve/match as appropriate and that localRuntimeConnectionPool was invoked with "/new-repo" (e.g., expect(localRuntimeConnectionPool.<sync/stream method>).toHaveBeenCalledWith("/new-repo", expect.objectContaining({ domain: "lane", action: "list" }) ) ). Ensure tests reference IPC.localRuntimeCallSync, IPC.localRuntimeStreamEvents and localRuntimeConnectionPool to mirror the existing test structure.apps/desktop/src/renderer/components/app/App.workKeepAlive.test.tsx (1)
291-313: 💤 Low valueConsider adding round-trip assertion for lanes keep-alive.
The work surface test (lines 183-212) verifies both directions: work → files → work, confirming the surface becomes active again. This test only verifies lanes → files. Adding the return navigation assertion would provide parity and catch any issues with lanes re-activation.
🧪 Suggested addition to complete round-trip coverage
expect(lanesLifecycle.mounts).toBe(1); expect(lanesLifecycle.unmounts).toBe(0); + + // Navigate back to lanes and verify reactivation + // (requires adding a "Return to lanes" button in FilesPage mock or using navigate directly) });Alternatively, extend the
FilesPagemock to include a "Return to lanes" button, then verify:
lanes-pageno longer hasaria-hidden='true'ancestordata-activereturns to"true"- Mount count remains at 1
🤖 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/app/App.workKeepAlive.test.tsx` around lines 291 - 313, Extend this test ("keeps the Lanes page mounted after visiting it and leaving for another tab") to perform the round-trip back to lanes: after navigating to the files page (using the existing fireEvent.click on the "Lanes open files" button and awaiting screen.findByTestId("files-page")), simulate a user action that returns to lanes (add a "Return to lanes" button to the FilesPage mock if needed), then assert that the lanes surface no longer has an ancestor with aria-hidden='true', that screen.getByTestId("lanes-page").getAttribute("data-active") === "true", and that lanesLifecycle.mounts remains 1 and lanesLifecycle.unmounts remains 0 to confirm it was not remounted.apps/desktop/scripts/validate-win-artifacts.mjs (1)
20-31: ⚡ Quick winUse camelCase for the new bundled skills variable name.
Rename this constant to camelCase and propagate the rename to usages.
As per coding guidelines,
**/*.{ts,tsx,js,jsx}: Use camelCase for variable names in TypeScript/JavaScript files.🤖 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/scripts/validate-win-artifacts.mjs` around lines 20 - 31, The constant BUNDLED_AGENT_SKILLS should be renamed to camelCase (e.g., bundledAgentSkills) and all references updated accordingly; locate the declaration of BUNDLED_AGENT_SKILLS and replace its name with bundledAgentSkills, then update every usage call site (imports, destructuring, or direct references) to the new identifier to ensure consistent naming across the codebase.apps/desktop/src/shared/adeCliGuidance.ts (1)
3-15: ⚡ Quick winUse camelCase for the new exported skill list constant.
Rename the constant to camelCase and update imports/usages accordingly.
As per coding guidelines,
**/*.{ts,tsx,js,jsx}: Use camelCase for variable names in TypeScript/JavaScript files.🤖 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/shared/adeCliGuidance.ts` around lines 3 - 15, Rename the exported constant ADE_BUNDLED_AGENT_SKILLS to camelCase (e.g., adeBundledAgentSkills) and update every import and internal usage to that new identifier; ensure the exported type remains "as const" and preserve the array contents, and run a project-wide search/replace for ADE_BUNDLED_AGENT_SKILLS to avoid unresolved references (update any tests or consumers that import it as well).apps/desktop/src/shared/agentSkillRoots.ts (1)
45-47: ⚡ Quick winRename new constants to camelCase to match repo naming rule.
Please rename these new constants to camelCase and update references to keep TS naming consistent.
As per coding guidelines,
**/*.{ts,tsx,js,jsx}: Use camelCase for variable names in TypeScript/JavaScript files.🤖 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/shared/agentSkillRoots.ts` around lines 45 - 47, Rename the exported constants to camelCase to follow repo naming conventions: change ANCESTOR_SKILL_DIRS to ancestorSkillDirs and PROMPT_AGENT_SKILL_ROOT_LIMIT to promptAgentSkillRootLimit, and update the related type name or usages referencing AncestorSkillDir if you choose to adjust it (or keep AncestorSkillDir as-is if type naming policy allows); then update all references throughout the codebase to use the new names (search for ANCESTOR_SKILL_DIRS and PROMPT_AGENT_SKILL_ROOT_LIMIT and replace with ancestorSkillDirs and promptAgentSkillRootLimit) and run TypeScript checks to ensure no broken imports or usages remain.apps/desktop/scripts/validate-mac-artifacts.mjs (1)
18-29: ⚡ Quick winUse camelCase for the new bundled skills variable name.
Please rename this new constant to camelCase and update call sites.
As per coding guidelines,
**/*.{ts,tsx,js,jsx}: Use camelCase for variable names in TypeScript/JavaScript files.🤖 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/scripts/validate-mac-artifacts.mjs` around lines 18 - 29, The constant BUNDLED_AGENT_SKILLS should be renamed to camelCase (e.g., bundledAgentSkills) and every reference updated accordingly; change the declaration of BUNDLED_AGENT_SKILLS to bundledAgentSkills and update all call sites/uses in this module and any imports/exports that reference that symbol (ensure exported names or destructured uses are adjusted too) so the variable follows the project's camelCase naming guideline.
🤖 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/ade-cli/src/adeRpcServer.ts`:
- Around line 2398-2413: prLinkUrls currently only forwards pr.githubUrl and may
omit a GitHub link even when repoOwner/repoName/prNumber are present; update
prLinkUrls (function prLinkUrls) to synthesize githubUrl when githubUrl is falsy
but repoOwner, repoName and prNumber exist (e.g. construct
"https://github.com/{repoOwner}/{repoName}/pull/{prNumber}" or use an existing
helper) and include it in the returned object alongside adeUrl so callers always
get a GitHub URL when coordinates are available.
In `@apps/desktop/resources/agent-skills/ade-deeplinks/SKILL.md`:
- Around line 124-129: The sentence fragment "for the ADE link." should be
merged into the surrounding text so the instruction flows; update the SKILL.md
section after the code block (the ade link pr example) to form a complete
sentence such as "Then include the printed ADE link. Prefer the default HTTPS
form in chat and terminal output because it is clickable, shareable, and
upgrades into the ADE PRs tab." — edit the text immediately following the code
block in the ade-deeplinks SKILL.md to replace the fragment with that complete
sentence.
In `@apps/desktop/src/main/services/ipc/runtimeBridge.ts`:
- Around line 620-626: The code currently trusts renderer-supplied arg.rootPath
(requestedRootPath → rootPath) and may route local runtime actions to arbitrary
paths; add an authorization check that resolves and validates any
renderer-provided rootPath against the window/session-authorized project scope
before using it. Implement or call a shared resolver like
verifyRendererRootPath(requestedRootPath, session, binding, windowId) that
returns either the authorized root (e.g., session.project.rootPath or
binding.rootPath) or null, and replace the direct assignment of rootPath with
the verified value; ensure this check is applied wherever requestedRootPath is
used (variables/functions referenced: requestedRootPath, rootPath, binding,
session, arg.rootPath).
In `@apps/desktop/src/preload/preload.ts`:
- Around line 1143-1152: localProjectBindingForRoot currently trims and returns
a routable OpenProjectBinding immediately from untrusted renderer input; instead
validate rootPath is non-empty/non-whitespace and do not promote it to a
routable binding until the main process confirms the switch. Update
localProjectBindingForRoot to reject empty/whitespace inputs and to return a
non-routable "pending" binding shape (e.g., include a confirmed: false or kind:
"local-pending") so callers like project.switchToPath won't be used for
privileged routing, and change project.switchToPath to only replace
currentProjectBinding with the confirmed binding after the main process
acknowledgement (or explicitly mark bindings as non-routable while pending).
Ensure all runtime consumers check the confirmed flag or binding kind before
using the binding for privileged routes.
In `@apps/desktop/src/renderer/components/chat/AgentChatPane.tsx`:
- Around line 5847-5849: The code currently sets
draftLaunchConfigTouchedKeyRef.current = draftLaunchConfigScopeKey only for some
draft edits but not when the executionMode field is changed, so late hydration
can overwrite a user-edited executionMode; update every handler or effect that
updates executionMode (references: executionMode, setExecutionMode or the event
handler that assigns executionMode) to also set
draftLaunchConfigTouchedKeyRef.current = draftLaunchConfigScopeKey when there is
no selectedSessionId (use the same conditional used in the existing draft touch
logic that checks selectedSessionId), and apply the same change to the other
occurrences noted (the other blocks where draftLaunchConfigTouchedKeyRef is set)
so executionMode edits mark the draft as touched consistently.
In `@apps/ios/ADE/App/DeepLinkURLParsing.swift`:
- Around line 6-12: splitRepo currently allows extra path segments because it
uses split(separator: "/", maxSplits: 1) which treats "owner/repo/extra" as
owner="owner" and repo="repo/extra"; change splitRepo to only accept exactly one
slash and reject any additional slashes by ensuring the input contains exactly
one "/" (or that the resulting repo string contains no "/" characters). Locate
the splitRepo function and replace the current split logic (value.split(...))
with a check that the string has exactly two components (owner and repo) and
that neither component is empty and repo contains no "/" characters before
returning (owner, repo).
---
Nitpick comments:
In `@apps/desktop/scripts/validate-mac-artifacts.mjs`:
- Around line 18-29: The constant BUNDLED_AGENT_SKILLS should be renamed to
camelCase (e.g., bundledAgentSkills) and every reference updated accordingly;
change the declaration of BUNDLED_AGENT_SKILLS to bundledAgentSkills and update
all call sites/uses in this module and any imports/exports that reference that
symbol (ensure exported names or destructured uses are adjusted too) so the
variable follows the project's camelCase naming guideline.
In `@apps/desktop/scripts/validate-win-artifacts.mjs`:
- Around line 20-31: The constant BUNDLED_AGENT_SKILLS should be renamed to
camelCase (e.g., bundledAgentSkills) and all references updated accordingly;
locate the declaration of BUNDLED_AGENT_SKILLS and replace its name with
bundledAgentSkills, then update every usage call site (imports, destructuring,
or direct references) to the new identifier to ensure consistent naming across
the codebase.
In `@apps/desktop/src/main/services/ai/tools/ctoOperatorTools.ts`:
- Around line 192-199: The buildAdePrUrl function duplicates logic already
present in workflowTools.ts; extract the deeplink construction into a shared
helper (e.g., a new exported function like createAdePrDeeplink or reuse an
existing shared module) and replace both buildAdePrUrl implementations to call
that helper; locate usages of buildAdePrUrl in ctoOperatorTools.ts and
workflowTools.ts and update imports to reference the new shared helper, ensuring
the helper takes a PrSummary (or the same repoOwner/repoName/prNumber fields)
and internally calls buildDeeplink.
In `@apps/desktop/src/main/services/ipc/runtimeBridge.test.ts`:
- Around line 197-239: Add tests mirroring the existing
IPC.localRuntimeCallAction case for the other two handlers:
IPC.localRuntimeCallSync and IPC.localRuntimeStreamEvents. Reuse the same
registerRuntimeBridge setup (including localRuntimeConnectionPool and
getWindowSession with binding "/old-repo"), invoke
ipcHandlers.get(IPC.localRuntimeCallSync) and
ipcHandlers.get(IPC.localRuntimeStreamEvents) with an eventForSender and a
payload containing rootPath: "/new-repo", then assert the returned values
resolve/match as appropriate and that localRuntimeConnectionPool was invoked
with "/new-repo" (e.g., expect(localRuntimeConnectionPool.<sync/stream
method>).toHaveBeenCalledWith("/new-repo", expect.objectContaining({ domain:
"lane", action: "list" }) ) ). Ensure tests reference IPC.localRuntimeCallSync,
IPC.localRuntimeStreamEvents and localRuntimeConnectionPool to mirror the
existing test structure.
In `@apps/desktop/src/renderer/components/app/App.workKeepAlive.test.tsx`:
- Around line 291-313: Extend this test ("keeps the Lanes page mounted after
visiting it and leaving for another tab") to perform the round-trip back to
lanes: after navigating to the files page (using the existing fireEvent.click on
the "Lanes open files" button and awaiting screen.findByTestId("files-page")),
simulate a user action that returns to lanes (add a "Return to lanes" button to
the FilesPage mock if needed), then assert that the lanes surface no longer has
an ancestor with aria-hidden='true', that
screen.getByTestId("lanes-page").getAttribute("data-active") === "true", and
that lanesLifecycle.mounts remains 1 and lanesLifecycle.unmounts remains 0 to
confirm it was not remounted.
In `@apps/desktop/src/shared/adeCliGuidance.ts`:
- Around line 3-15: Rename the exported constant ADE_BUNDLED_AGENT_SKILLS to
camelCase (e.g., adeBundledAgentSkills) and update every import and internal
usage to that new identifier; ensure the exported type remains "as const" and
preserve the array contents, and run a project-wide search/replace for
ADE_BUNDLED_AGENT_SKILLS to avoid unresolved references (update any tests or
consumers that import it as well).
In `@apps/desktop/src/shared/agentSkillRoots.ts`:
- Around line 45-47: Rename the exported constants to camelCase to follow repo
naming conventions: change ANCESTOR_SKILL_DIRS to ancestorSkillDirs and
PROMPT_AGENT_SKILL_ROOT_LIMIT to promptAgentSkillRootLimit, and update the
related type name or usages referencing AncestorSkillDir if you choose to adjust
it (or keep AncestorSkillDir as-is if type naming policy allows); then update
all references throughout the codebase to use the new names (search for
ANCESTOR_SKILL_DIRS and PROMPT_AGENT_SKILL_ROOT_LIMIT and replace with
ancestorSkillDirs and promptAgentSkillRootLimit) and run TypeScript checks to
ensure no broken imports or usages remain.
🪄 Autofix (Beta)
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
Run ID: 6981b48b-cf5b-48b9-a717-e5da76fc3a74
⛔ Files ignored due to path filters (19)
apps/ios/ADE.xcodeproj/project.pbxprojis excluded by!**/*.xcodeproj/project.pbxprojdocs/ARCHITECTURE.mdis excluded by!docs/**docs/features/ade-code/README.mdis excluded by!docs/**docs/features/agents/README.mdis excluded by!docs/**docs/features/agents/tool-registration.mdis excluded by!docs/**docs/features/chat/README.mdis excluded by!docs/**docs/features/chat/composer-and-ui.mdis excluded by!docs/**docs/features/computer-use/app-control.mdis excluded by!docs/**docs/features/deeplinks/README.mdis excluded by!docs/**docs/features/ios-simulator/README.mdis excluded by!docs/**docs/features/lanes/README.mdis excluded by!docs/**docs/features/project-home/README.mdis excluded by!docs/**docs/features/pull-requests/README.mdis excluded by!docs/**docs/features/remote-runtime/README.mdis excluded by!docs/**docs/features/remote-runtime/internal-architecture.mdis excluded by!docs/**docs/features/sync-and-multi-device/README.mdis excluded by!docs/**docs/features/sync-and-multi-device/remote-commands.mdis excluded by!docs/**docs/features/terminals-and-sessions/README.mdis excluded by!docs/**docs/playbooks/ship-lane.mdis excluded by!docs/**
📒 Files selected for processing (44)
apps/ade-cli/README.mdapps/ade-cli/src/adeRpcServer.test.tsapps/ade-cli/src/adeRpcServer.tsapps/ade-cli/src/bootstrap.tsapps/ade-cli/src/cli.test.tsapps/ade-cli/src/cli.tsapps/ade-cli/src/tuiClient/__tests__/commands.test.tsapps/ade-cli/src/tuiClient/__tests__/rightPaneFormatters.test.tsapps/ade-cli/src/tuiClient/app.tsxapps/ade-cli/src/tuiClient/commands.tsapps/ade-cli/src/tuiClient/rightPaneFormatters.tsapps/desktop/resources/agent-skills/ade-deeplinks/SKILL.mdapps/desktop/resources/agent-skills/ade-pr-workflows/SKILL.mdapps/desktop/scripts/validate-mac-artifacts.mjsapps/desktop/scripts/validate-win-artifacts.mjsapps/desktop/src/main/services/ai/tools/ctoOperatorTools.tsapps/desktop/src/main/services/ai/tools/systemPrompt.test.tsapps/desktop/src/main/services/ai/tools/workflowTools.tsapps/desktop/src/main/services/chat/agentChatService.test.tsapps/desktop/src/main/services/chat/agentChatService.tsapps/desktop/src/main/services/chat/claudeSlashCommandDiscovery.test.tsapps/desktop/src/main/services/chat/claudeSlashCommandDiscovery.tsapps/desktop/src/main/services/ipc/runtimeBridge.test.tsapps/desktop/src/main/services/ipc/runtimeBridge.tsapps/desktop/src/preload/preload.test.tsapps/desktop/src/preload/preload.tsapps/desktop/src/renderer/components/app/App.tsxapps/desktop/src/renderer/components/app/App.workKeepAlive.test.tsxapps/desktop/src/renderer/components/chat/AgentChatPane.submit.test.tsxapps/desktop/src/renderer/components/chat/AgentChatPane.tsxapps/desktop/src/renderer/components/lanes/useLaneWorkSessions.test.tsapps/desktop/src/renderer/components/lanes/useLaneWorkSessions.tsapps/desktop/src/renderer/components/terminals/cliLaunch.test.tsapps/desktop/src/renderer/state/appStore.test.tsapps/desktop/src/renderer/state/appStore.tsapps/desktop/src/shared/adeCliGuidance.test.tsapps/desktop/src/shared/adeCliGuidance.tsapps/desktop/src/shared/agentSkillRoots.test.tsapps/desktop/src/shared/agentSkillRoots.tsapps/desktop/src/shared/cliLaunch.tsapps/ios/ADE/App/DeepLinkRouter.swiftapps/ios/ADE/App/DeepLinkURLParsing.swiftapps/ios/ADE/Views/Deeplinks/SendToMacCard.swiftapps/ios/ADETests/ADETests.swift
|
@copilot review but do not make fixes |


Summary
Describe the change.
What Changed
Key files and behaviors.
Validation
How you tested.
Risks
Anything to watch.
Summary by CodeRabbit
New Features
Improvements
Greptile Summary
This PR delivers the "Refreshing Lanes Tabs" milestone: the Lanes surface is now kept alive (keep-alive) across tab switches, mirroring the existing Work surface pattern. Project switching restores lane/session caches on warm tab switches, draft chat mode preserves user-selected model/provider during lane hydration, and CLI PR creation now outputs both GitHub and ADE URLs.
App.tsx: alanesSurfaceparallel toworkSurfaceis mounted on first/lanesvisit and kept hidden (CSS +inertattribute) rather than unmounted; aProjectTransitionVeiloverlays the tab host during cold project switches.useLaneWorkSessions:refreshcallback'slaneId/projectRootcaptures replaced with refs updated in auseEffect, preventing stale fetch targets when lanes or projects switch mid-request; two dedicated test cases cover the mid-refresh scenarios.runtimeBridge.tstrust boundary hardened:resolveAuthorizedLocalRuntimeRootPathvalidates renderer-suppliedrootPathagainst the window session's authorized roots (binding, active project, open project tabs) before connecting to the local runtime pool.Confidence Score: 5/5
Safe to merge — changes are additive, well-tested, and the runtimeBridge trust boundary is now properly enforced.
The lanes keep-alive mirrors a proven pattern already used for the Work surface, the stale-closure fix in useLaneWorkSessions is backed by two targeted mid-refresh tests, and the IPC rootPath authorization in runtimeBridge now validates against the full set of the window's authorized project roots rather than accepting an arbitrary renderer-supplied path. No functional regressions were found across the changed paths.
No files require special attention.
Important Files Changed
Flowchart
%%{init: {'theme': 'neutral'}}%% flowchart TD A[User navigates to /lanes] --> B{lanesMounted?} B -- No --> C[Mount LanesPage\nlanesMounted = true] B -- Yes --> D[Show cached LanesPage\nremove inert attr] C --> E[LanesPage visible & active] D --> E E --> F[User navigates away] F --> G[Set inert + aria-hidden\nopacity:0 / z-index:-1] G --> H[LanesPage stays mounted\nin background] H --> I[User returns to /lanes] I --> D J[Project tab switch] --> K{Warm switch?} K -- Yes --> L[Restore laneCacheByProject\nrestore laneSelectionByProject] K -- No --> M[Show ProjectTransitionVeil\nlanesLoading: true] L --> N[Lanes surface hydrated instantly] M --> O[Full project load\nclear caches]Comments Outside Diff (1)
apps/desktop/src/main/services/ipc/runtimeBridge.ts, line 617-636 (link)The three IPC handlers (
localRuntimeCallAction,localRuntimeCallSync,localRuntimeStreamEvents) now accept a renderer-suppliedrootPath, which is used directly — after only atrim()— to connect to the local runtime pool and create event subscriptions. Previously, the root was always derived from the window session's trusted binding. A compromised or malicious renderer page can now direct IPC calls to any path on disk (e.g."/"or a path belonging to another project). For a desktop app with controlled renderer content this is lower risk, but the trust boundary change is worth a second look before shipping.Prompt To Fix With AI
Reviews (5): Last reviewed commit: "ship: iteration 2 - address coderabbit r..." | Re-trigger Greptile