Skip to content

perf(lanes): reduce hidden-work and session refresh load#514

Merged
arul28 merged 13 commits into
mainfrom
autoresearch/lanes-lanes-20260531-1421
Jun 2, 2026
Merged

perf(lanes): reduce hidden-work and session refresh load#514
arul28 merged 13 commits into
mainfrom
autoresearch/lanes-lanes-20260531-1421

Conversation

@arul28
Copy link
Copy Markdown
Owner

@arul28 arul28 commented Jun 2, 2026

Summary

  • Reduce Lanes and Work tab background load by gating stack graph roster hydration, hidden work panes, minimized git action panes, PR tag refreshes, and session-list invalidation.
  • Add app/PTY resource usage snapshots so the renderer can adapt terminal grid refresh rates under CPU, memory, or event-loop pressure.
  • Tighten hidden terminal parking accessibility and keep App Control dev launch guidance discoverable.

What changed

  • Main process exposes cached app resource usage from runtime PIDs and PTY process trees without trusting stale owner PIDs.
  • Renderer resource pressure is coalesced and used by TopBar and WorkViewArea to reduce refresh pressure while visible behavior stays intact.
  • Lanes session refreshes are scoped by project/lane/session ids and deferred while hidden; PR refreshes are opportunistic and no longer cancel full tag snapshots.
  • Tests cover session-list cache scoping, hidden-refresh deferral, PR refresh behavior, terminal parking, resource pressure, PTY sampling, and affected lane/work surfaces.

Validation

  • npm --prefix apps/desktop run typecheck
  • npm --prefix apps/ade-cli run typecheck
  • npm --prefix apps/web run typecheck
  • npm --prefix apps/desktop run lint
  • npm run test:desktop:sharded
  • npm --prefix apps/ade-cli run test
  • npm --prefix apps/desktop run build
  • npm --prefix apps/ade-cli run build
  • npm --prefix apps/web run build
  • node scripts/validate-docs.mjs
  • docs feature Source file map check
  • docs PRD markdown link check
  • post-rebase focused desktop tests for TopBar, LanesPage, LaneGitActionsPane, CommitTimeline, TerminalView, WorkViewArea, useWorkSessions, useLaneWorkSessions, sessionListCache, ptyService, sessionService, agentChatService

Risks

  • The main risk is over-throttling visible session or PR refreshes; focused tests cover visible refresh, reveal refresh, and full snapshot fallback behavior.

ADE   Open in ADE  ·  autoresearch/lanes-lanes-20260531-1421 branch  ·  PR #514

Summary by CodeRabbit

  • New Features

    • Added resource pressure indicator to TopBar showing system load from terminal operations
    • Implemented adaptive grid terminal refresh that adjusts based on detected system pressure
    • Added visibility-aware session refresh that defers updates when tabs are hidden
  • Improvements

    • Optimized chat session filtering and PR refresh scheduling
    • Improved terminal rendering efficiency through deferred pane mounting and targeted background updates
    • Enhanced session list management with better filtering and caching

Greptile Summary

This PR reduces background CPU and IPC load across the Lanes and Work surfaces by gating expensive operations (stack-graph roster hydration, hidden-pane mounting, minimized git-action panes, PR tag refreshes, session-list invalidation) on visibility and activity. It also adds app/PTY resource-usage snapshots piped from the main process to the renderer for adaptive terminal-grid refresh rate throttling.

  • Main process: new appGetResourceUsage IPC handler samples Electron app metrics + PTY process trees via a shared ps call (900 ms cache); sessionService.list() gains a toolTypes multi-query filter used by agentChatService to avoid loading non-chat sessions.
  • Renderer: resourcePressure.ts coalesces IPC fetches and converts signals (CPU %, heap ratio, event-loop drift) into a 0–4 pressure level; WorkViewArea uses FNV-1a bucket rotation to stagger inactive grid-terminal refreshes under load; TopBar shows a ResourcePressureIndicator at level > 0.
  • Lanes/Work session refresh: both useLaneWorkSessions and useWorkSessions defer session-list refreshes while the document is hidden and flush on visibility restore; LanesPage splits lane-runtime events into fast lifecycle vs. slow data buckets and schedules per-PR opportunistic refreshes for visible lanes.

Confidence Score: 5/5

The change is safe to merge; the one code-quality note is a defensive fix for a silently-failing native method call.

All new gating logic uses conservative visibility and activity guards, the adaptive throttling degrades gracefully back to full-speed for active sessions, and the scoped cache-invalidation over-invalidates rather than under-invalidates. The only concrete defect is in getSystemMemoryMB: the Electron native method is detached from its receiver before calling, which will throw on Electron builds that enforce this binding — but the try/catch silently returns null, so memory pressure readings just go missing rather than crashing. The rest of the diff is well-structured and thoroughly tested.

apps/desktop/src/main/services/ipc/registerIpc.ts — the getSystemMemoryMB unbound call.

Important Files Changed

Filename Overview
apps/desktop/src/main/services/ipc/registerIpc.ts Adds appGetResourceUsage IPC handler with a 900 ms module-level cache. Introduces getSystemMemoryMB with a detached-method call that will silently return null on most Electron builds; all other helpers look correct.
apps/desktop/src/main/services/pty/ptyService.ts Adds readProcessMetricRows (single spawnSync("ps")), collectProcessTreePids, sampleProcessTreeResourceUsage, and getResourceUsageSnapshot to the service. Logic is sound; shared ProcessMetricRowsProvider parameter prevents double ps spawns per IPC call.
apps/desktop/src/main/services/sessions/sessionService.ts Adds toolTypes filter to list() via separate per-type SQL queries merged in-memory. Each sub-query correctly reuses the base laneId/status WHERE clauses and applies the effective limit at the SQL level before the final in-memory deduplicate-sort-slice.
apps/desktop/src/renderer/lib/resourcePressure.ts New module providing coalesced IPC fetch, pressure-level helpers, and a human-readable description. freeMemoryMB null-guard uses == null (correct — doesn't suppress 0), and clampPressureLevel uses Math.trunc.
apps/desktop/src/renderer/lib/sessionListCache.ts Adds toolTypes to cache key, removes the projectRoot option (now always read from AppStore), and adds scoped invalidation. Scope parsing correctly over-invalidates (never under-invalidates) when toolTypes varies across entries sharing the same project+lane.
apps/desktop/src/renderer/components/terminals/WorkViewArea.tsx Adds adaptive grid-terminal refresh backed by drift, heap-ratio, and app-resource signals. Bucket-based throttling, FNV-1a stableBucketForSession, and the stabilize-down-by-one logic all look correct.
apps/desktop/src/renderer/components/lanes/LanesPage.tsx Significant refactor: deferred pane mounting, scoped per-PR refresh, lane-runtime event split into lifecycle vs data buckets, and agent roster gated on stack-graph visibility. laneVisiblePrRefreshRequestedAtRef is pre-marked before the 260 ms timer fires, but the normal PR poller is the stated fallback.
apps/desktop/src/renderer/components/lanes/useLaneWorkSessions.ts Adds pendingHiddenSessionRefreshRef, scoped invalidateSessionListCache, session-ID guard on onExit, and lane-ID guard on agentChat.onEvent. Visibility-restore refresh is correctly scoped and handles project/lane changes.
apps/desktop/src/renderer/components/terminals/useWorkSessions.ts Mirrors useLaneWorkSessions pattern: adds pendingHiddenSessionRefreshRef, removes projectRoot option from listSessionsCached calls, and unifies cache-invalidation + refresh scheduling through markSessionListDirtyOrRefresh.
apps/desktop/src/renderer/components/terminals/TerminalView.tsx Adds configureParkedRoot for explicit aria-hidden/inert/contain:strict on the parking container, deduplicates rogue parking nodes, and calls setRuntimeInteractionState(runtime, false) before parking to clean up focus/interaction state.
apps/desktop/src/renderer/components/app/TopBar.tsx Adds ResourcePressureIndicator and useResourcePressureUsage hook. Indicator only renders at level > 0, uses a role=status element with aria-label and title.
apps/desktop/src/renderer/components/lanes/lanePageModel.ts Adds selectVisibleLanePrRefreshIds (stale-check + recently-requested guard, capped at 4 PRs) and getDeferredLanePaneDelayMs (position-based step with a 3.3 s cap). Both are pure functions and covered by tests.

Sequence Diagram

sequenceDiagram
    participant Renderer
    participant Preload
    participant MainIPC as Main IPC (registerIpc)
    participant PtyService
    participant AppMetrics as Electron app.getAppMetrics()
    participant OS as process.getSystemMemoryInfo()

    Renderer->>Preload: window.ade.app.getResourceUsage()
    Preload->>MainIPC: IPC appGetResourceUsage
    Note over MainIPC: Cache hit? (< 900 ms)
    MainIPC->>AppMetrics: app.getAppMetrics()
    MainIPC->>PtyService: getResourceUsageSnapshot(sharedReadRows)
    PtyService->>OS: spawnSync("ps") via readProcessMetricRows (once, shared)
    PtyService-->>MainIPC: PtyProcessResourceUsageSnapshot
    MainIPC->>OS: getSystemMemoryInfo() (unbound — see comment)
    MainIPC-->>Preload: AppResourceUsageSnapshot (cached)
    Preload-->>Renderer: snapshot

    Renderer->>Renderer: pressureLevelForSignals(driftMs, heapRatio, usage)
    Renderer->>Renderer: gridTerminalRefreshPolicyForPressure(level)
    Renderer->>Renderer: shouldStreamGridTerminal(sessionId, bucket, pulse)
Loading

Fix All in Claude Code

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
apps/desktop/src/main/services/ipc/registerIpc.ts:821-826
The method `getSystemMemoryInfo` is detached from `electronProcess` before being called (`const read = ...; read()`), losing its `this` binding. Electron's `process.getSystemMemoryInfo` is a native method that typically requires the original receiver; calling it as a free function will throw an "Illegal invocation" or TypeError on most Electron versions. The `try/catch` handles it gracefully (returning `null`), but that means system-memory pressure readings will be silently absent for the entire session. Calling it directly on `electronProcess` avoids the problem.

```suggestion
  if (typeof electronProcess.getSystemMemoryInfo !== "function") {
    return { freeMemoryMB: null, totalMemoryMB: null };
  }
  try {
    const info = electronProcess.getSystemMemoryInfo();
```

Reviews (2): Last reviewed commit: "test(sessions): align refresh cache expe..." | Re-trigger Greptile

arul28 added 9 commits June 2, 2026 14:40
Measured with perf-pass run lanes-20260531-1421-after1 against baseline lanes-20260531-1421-baseline. Lanes navigation localRuntime.callAction count dropped 87 -> 28 and runtime IPC duration dropped 25.4s -> 13.3s. Stack Graph open now hydrates agent rosters on demand, adding 63 callAction calls totaling 450ms.
Minimized Work lane switch local-runtime callAction dropped 22 -> 16 calls and 2230ms -> 1545ms summed duration in lanes-20260531-compare-candidates-2.
CLI-heavy benchmark with 50k shell sessions and 20 chat sessions improved chat session query time from 11.6ms to 0.079ms per call by using lane/tool indexes and separating legacy fallback rows.
@vercel
Copy link
Copy Markdown

vercel Bot commented Jun 2, 2026

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
ade Ignored Ignored Preview Jun 2, 2026 7:18pm

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 2, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

This PR unifies multiple performance optimizations across the Lanes tab: session filtering by tool type, real-time app resource usage monitoring with pressure indicators, visibility-aware refresh deferral for background operations, deferred pane mounting with staggered timing, activity-based gating of Git Actions side effects, PR refresh scheduling for visible lanes, terminal visibility management, and adaptive grid terminal refresh based on system pressure.

Changes

Lanes Tab Performance Optimization

Layer / File(s) Summary
Session filtering by tool types
apps/desktop/src/main/services/sessions/sessionService.ts, apps/desktop/src/shared/types/sessions.ts, apps/desktop/src/main/services/chat/agentChatService.ts, apps/desktop/src/main/services/state/kvDb.ts, apps/desktop/src/renderer/lib/sessionListCache.ts, apps/desktop/src/main/services/sessions/sessionService.test.ts, apps/desktop/src/main/services/chat/agentChatService.test.ts, apps/desktop/src/renderer/lib/sessionListCache.test.ts
Backend sessionService.list now filters by optional toolTypes array before applying limits; legacy resume_command patterns supported for chat sessions. Frontend cache keys and scoped invalidation incorporate toolTypes. Chat service calls with centralized CHAT_SESSION_TOOL_TYPES constant. Database indexes added for (lane_id, tool_type, started_at) and (tool_type, started_at).
App resource usage snapshot collection
apps/desktop/src/shared/types/core.ts, apps/desktop/src/main/services/pty/ptyService.ts, apps/desktop/src/main/services/localRuntime/localRuntimeConnectionPool.ts, apps/desktop/src/main/services/ipc/registerIpc.ts, apps/desktop/src/shared/ipc.ts
PTY service exports sampleProcessTreeResourceUsage() to read live PTY process metrics via ps. Runtime pool tracks activeRuntimePid and exposes getRuntimeProcessIds(). New IPC endpoint appGetResourceUsage aggregates Electron process metrics, system memory, and PTY usage into cached AppResourceUsageSnapshot (900ms cache).
Resource usage preload bridge
apps/desktop/src/preload/global.d.ts, apps/desktop/src/preload/preload.ts, apps/desktop/src/renderer/browserMock.ts
Preload exposes ade.app.getResourceUsage() method returning Promise<AppResourceUsageSnapshot>. Browser mock provides deterministic test values.
Resource pressure indicator
apps/desktop/src/renderer/lib/resourcePressure.ts, apps/desktop/src/renderer/components/app/TopBar.tsx, apps/desktop/src/renderer/components/app/TopBar.test.tsx
New library computes 0–4 pressure level from CPU/memory utilization and formats human-readable descriptions. TopBar samples usage on interval and visibility changes, renders warning icon when pressure nonzero. Hook coalesces concurrent requests and clears listeners on cleanup.
Visibility-aware refresh deferral
apps/desktop/src/renderer/components/terminals/useWorkSessions.ts, apps/desktop/src/renderer/components/lanes/useLaneWorkSessions.ts, apps/desktop/src/renderer/components/terminals/useWorkSessions.test.ts, apps/desktop/src/renderer/components/lanes/useLaneWorkSessions.test.ts
Work sessions hooks defer cache invalidation and refresh scheduling when document is hidden; pending refresh flag triggers immediate refresh when tab becomes visible. Per-event delays (PTY: 120ms, chat: 220ms, session-change: 80ms) routed through visibility-aware helper.
Pane activity gating
apps/desktop/src/renderer/components/lanes/CommitTimeline.tsx, apps/desktop/src/renderer/components/lanes/LaneGitActionsPane.tsx, apps/desktop/src/renderer/components/lanes/CommitTimeline.test.tsx, apps/desktop/src/renderer/components/lanes/LaneGitActionsPane.test.tsx
CommitTimeline and LaneGitActionsPane accept optional active prop (default true). Background effects (git metadata, auto-rebase status, sync polling, event subscriptions) early-return when active is false, avoiding work for inactive panes.
Pane rendering and mounting
apps/desktop/src/renderer/components/ui/PaneTilingLayout.tsx, apps/desktop/src/renderer/components/lanes/lanePageModel.ts, apps/desktop/src/renderer/components/lanes/LanesPage.tsx, apps/desktop/src/renderer/components/lanes/LanesPage.test.ts
PaneTilingLayout supports optional renderChildren callback for dynamic pane content. LanesPage adds DeferredLanePane wrapper with configurable delayMs (computed via getDeferredLanePaneDelayMs) to stagger pane mount timing. Stack Graph roster computation gated by header visibility. Work pane mounting uses renderChildren with minimized gating.
PR refresh for visible lanes
apps/desktop/src/renderer/components/lanes/LanesPage.tsx
New effect selects visible PR IDs via selectVisibleLanePrRefreshIds (filters by staleness, recent-request cooldown, limit=4); debounced background refresh merges updated summaries by PR id.
Terminal parking and visibility
apps/desktop/src/renderer/components/terminals/TerminalView.tsx, apps/desktop/src/renderer/components/terminals/TerminalView.test.tsx
Parked terminal runtime container marked aria-hidden, inert, non-focusable, and visually hidden via styles/contain. Added data attributes (data-ade-terminal-visible, data-ade-terminal-active, data-ade-terminal-session-id) for visibility tracking.
Adaptive grid terminal refresh
apps/desktop/src/renderer/components/terminals/WorkViewArea.tsx, apps/desktop/src/renderer/components/terminals/WorkViewArea.test.tsx
Grid terminals adapt refresh cadence based on pressure signals (drift, renderer heap, app resource usage). useAdaptiveGridTerminalRefresh computes policy (bucket count, pulse interval) and assigns sessions to buckets. Non-active terminals suppressed when pressure is high. Grid container exposes policy/bucket/pulse via data attributes.
Performance patterns documentation
.agents/skills/ade-perf-lanes/SKILL.md
Updated skill doc version 0.2.0 → 0.2.2 with proven patterns: Stack Graph roster gating, chat session filtering before caps, stale-PR refresh with dedupe/caps, Git Actions pane effect pausing when minimized with deferred mounting.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • arul28/ADE#116: Both PRs modify apps/desktop/src/renderer/components/lanes/useLaneWorkSessions.ts refresh/session-list logic (one adds refresh/waiter & ordering changes, the other adds visibility-aware deferred invalidation/refresh), so the changes are code-level related.
  • arul28/ADE#328: Both PRs modify the /lanes behavior and specifically touch useLaneWorkSessions.ts refresh logic (main PR adds ref/visibility-aware refresh deferral while the retrieved PR fixes the stale-closure by reading laneId/projectRoot from refs), making the changes code-level related.

Suggested labels

desktop, docs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 2.30% 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
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.
Title check ✅ Passed The title 'perf(lanes): reduce hidden-work and session refresh load' directly and concisely summarizes the primary change—performance optimization for lanes by reducing refresh overhead for hidden work and sessions.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch autoresearch/lanes-lanes-20260531-1421

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 and usage tips.

@arul28 arul28 changed the title Autoresearch Lanes Lanes 20260531 1421 perf(lanes): reduce hidden-work and session refresh load Jun 2, 2026
@arul28
Copy link
Copy Markdown
Owner Author

arul28 commented Jun 2, 2026

@copilot review but do not make fixes

Comment thread apps/desktop/src/main/services/ipc/registerIpc.ts Outdated
Comment thread apps/desktop/src/renderer/lib/resourcePressure.ts Outdated
Comment thread apps/desktop/src/renderer/components/terminals/WorkViewArea.tsx
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

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 (1)
apps/desktop/src/renderer/lib/sessionListCache.ts (1)

66-92: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

projectRoot only changes the cache key, not the data being fetched.

When options.projectRoot is set, this path namespaces the cache entry under that root, but the actual fetch still calls window.ade.sessions.list(normalizeArgs(args)). If the active project in useAppStore is different, you can cache /project/a rows under a /project/b key and then serve the wrong sessions on later reads. Either plumb projectRoot through the IPC/shared/preload contract or remove the override until the fetch can honor it. As per coding guidelines, "Keep IPC contracts, preload types, shared types, and renderer usage in sync whenever an interface changes."

🤖 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/lib/sessionListCache.ts` around lines 66 - 92, The
cache key uses options.projectRoot but the fetch still calls
window.ade.sessions.list(normalizeArgs(args)), which can return sessions for a
different active project; update the fetch to honor the projectRoot (or stop
namespacing the key) by passing options.projectRoot into the normalized args
used by window.ade.sessions.list (e.g., extend normalizeArgs(args) to accept
projectRoot and call window.ade.sessions.list(normalizeArgs(args,
options?.projectRoot)) so the data fetched matches the cache key), or remove the
projectRoot override entirely from the key until the IPC/preload contract is
updated.
🧹 Nitpick comments (2)
apps/desktop/src/main/services/chat/agentChatService.ts (1)

2551-2557: ⚡ Quick win

Consider deriving the type guard from the constant to eliminate duplication.

The CHAT_SESSION_TOOL_TYPES constant and the isChatToolType type guard (lines 2559-2561) both hardcode the same list of chat tool types. If a new chat tool type is added, both locations must be updated, creating a maintenance hazard.

♻️ Suggested refactor to derive the type from the constant
+type ChatToolType = (typeof CHAT_SESSION_TOOL_TYPES)[number];
+
 function isChatToolType(
   toolType: TerminalToolType | null | undefined,
-): toolType is "codex-chat" | "claude-chat" | "opencode-chat" | "cursor" | "droid-chat" {
+): toolType is ChatToolType {
+  return toolType != null && CHAT_SESSION_TOOL_TYPES.includes(toolType as ChatToolType);
-  return (
-    toolType === "codex-chat" ||
-    toolType === "claude-chat" ||
-    toolType === "opencode-chat" ||
-    toolType === "cursor" ||
-    toolType === "droid-chat"
-  );
 }
🤖 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/chat/agentChatService.ts` around lines 2551 -
2557, The CHAT_SESSION_TOOL_TYPES array is duplicated in the isChatToolType
guard causing maintenance drift; update isChatToolType to derive membership from
the CHAT_SESSION_TOOL_TYPES constant instead of re-listing values (e.g., ensure
CHAT_SESSION_TOOL_TYPES is a literal/readonly array and have isChatToolType
return CHAT_SESSION_TOOL_TYPES.includes(value as TerminalToolType)), so adding
new chat tool types requires changing only CHAT_SESSION_TOOL_TYPES.
apps/desktop/src/renderer/components/terminals/TerminalView.tsx (1)

649-671: ⚡ Quick win

Make inert attribute handling consistent with aria-hidden.

The aria-hidden attribute now uses explicit removeAttribute/setAttribute (lines 658-662), which is clearer than the previous toggle-based approach. However, the inert attribute still uses toggleAttribute (line 667), creating an inconsistency in the same function.

♻️ Suggested refactor for consistency
   try {
     if (active) {
       runtime.host.removeAttribute("aria-hidden");
     } else {
       runtime.host.setAttribute("aria-hidden", "true");
     }
   } catch {
     // ignore
   }
   try {
-    runtime.host.toggleAttribute("inert", !active);
+    if (active) {
+      runtime.host.removeAttribute("inert");
+    } else {
+      runtime.host.setAttribute("inert", "");
+    }
   } catch {
     // ignore
   }
🤖 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/terminals/TerminalView.tsx` around lines
649 - 671, Summary: Make inert attribute handling consistent with aria-hidden by
using explicit setAttribute/removeAttribute in setRuntimeInteractionState. In
function setRuntimeInteractionState, replace the
runtime.host.toggleAttribute("inert", !active) usage with explicit calls: when
active is true call runtime.host.removeAttribute("inert"), otherwise call
runtime.host.setAttribute("inert", "true") (or set empty string) inside the
existing try/catch so behavior matches the aria-hidden branch; keep the same
runtime and host references.
🤖 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/main/services/ipc/registerIpc.ts`:
- Around line 810-822: getAppResourceUsageSnapshot mixes global Electron metrics
(app.getAppMetrics()) with PTY/runtime usage from a single context (ptyService,
sessionService, localRuntimeConnectionPool, processRegistry), producing
inconsistent totals; fix by either aggregating PTY/runtime usage across all
active contexts or returning a per-window scoped snapshot: update
getAppResourceUsageSnapshot (and any callers) to either iterate all contexts to
sum combinePtyResourceUsage and getRuntimeOwnedPtyUsage, or change the API to
accept a window/sender identifier and only use app.getAppMetrics() together with
the matching context's PTY/runtime snapshot so metrics are consistent (apply
same change pattern used around the other occurrence noted at lines ~3530-3538).

In `@apps/desktop/src/renderer/components/lanes/LanesPage.tsx`:
- Around line 1149-1185: The effect in LanesPage.tsx that runs the opportunistic
PR refresh bails when document.visibilityState !== "visible" but won't re-run on
hidden→visible transitions because visibility isn't in the dependency list; add
a visibility-aware trigger (e.g., a small piece of state like isDocumentVisible
or a "visibilitychange" listener) and include that state in the useEffect
dependency array so the effect re-evaluates when the tab becomes visible again;
update the useEffect (the block that reads project?.rootPath, active,
selectVisibleLanePrRefreshIds, and sets
laneVisiblePrRefreshRequestedAtRef/current timers) to depend on this new
visibility signal so the refresh selection runs on visibilitychange.
- Around line 201-209: The effect currently resets ready whenever delayMs or
cacheKey changes, causing remounts; change it to only apply the initial delay
the first time a given cacheKey appears. Implement a persistent ref/Set (e.g.,
initializedCacheKeys via useRef) and in the useEffect for cacheKey/delayMs
check: if initializedCacheKeys has cacheKey, immediately setReady(true) and do
not toggle to false or start a timer; otherwise add cacheKey to the Set, apply
the existing delay behavior (setReady(false), start timer -> setReady(true)),
and call clearTimeout in the cleanup. Keep references to cacheKey, delayMs,
setReady, and the useEffect as the location to modify.

In `@apps/desktop/src/renderer/lib/resourcePressure.ts`:
- Around line 75-79: The function formatSystemMemory incorrectly treats
freeMemoryMB === 0 as missing; change the falsy checks to explicit
null/undefined checks so zero is accepted: in formatSystemMemory, replace the
condition "if (!usage?.freeMemoryMB || !usage.totalMemoryMB ||
usage.totalMemoryMB <= 0) return null;" with explicit checks like "if (usage ==
null || usage.freeMemoryMB == null || usage.totalMemoryMB == null ||
usage.totalMemoryMB <= 0) return null;" so that usage.freeMemoryMB === 0 yields
"100% system memory used" as expected.

In `@apps/desktop/src/renderer/lib/sessionListCache.ts`:
- Around line 25-29: The toolTypes branch keeps original strings so values with
surrounding whitespace are treated as different keys; change the pipeline in the
block handling args.toolTypes (where normalized.toolTypes is set) to trim each
toolType first, filter out empty trimmed strings, then deduplicate (e.g., via
new Set) and sort, and assign the resulting array to normalized.toolTypes so all
entries are stored and cached using their trimmed form.

---

Outside diff comments:
In `@apps/desktop/src/renderer/lib/sessionListCache.ts`:
- Around line 66-92: The cache key uses options.projectRoot but the fetch still
calls window.ade.sessions.list(normalizeArgs(args)), which can return sessions
for a different active project; update the fetch to honor the projectRoot (or
stop namespacing the key) by passing options.projectRoot into the normalized
args used by window.ade.sessions.list (e.g., extend normalizeArgs(args) to
accept projectRoot and call window.ade.sessions.list(normalizeArgs(args,
options?.projectRoot)) so the data fetched matches the cache key), or remove the
projectRoot override entirely from the key until the IPC/preload contract is
updated.

---

Nitpick comments:
In `@apps/desktop/src/main/services/chat/agentChatService.ts`:
- Around line 2551-2557: The CHAT_SESSION_TOOL_TYPES array is duplicated in the
isChatToolType guard causing maintenance drift; update isChatToolType to derive
membership from the CHAT_SESSION_TOOL_TYPES constant instead of re-listing
values (e.g., ensure CHAT_SESSION_TOOL_TYPES is a literal/readonly array and
have isChatToolType return CHAT_SESSION_TOOL_TYPES.includes(value as
TerminalToolType)), so adding new chat tool types requires changing only
CHAT_SESSION_TOOL_TYPES.

In `@apps/desktop/src/renderer/components/terminals/TerminalView.tsx`:
- Around line 649-671: Summary: Make inert attribute handling consistent with
aria-hidden by using explicit setAttribute/removeAttribute in
setRuntimeInteractionState. In function setRuntimeInteractionState, replace the
runtime.host.toggleAttribute("inert", !active) usage with explicit calls: when
active is true call runtime.host.removeAttribute("inert"), otherwise call
runtime.host.setAttribute("inert", "true") (or set empty string) inside the
existing try/catch so behavior matches the aria-hidden branch; keep the same
runtime and host references.
🪄 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: 814fd50b-4a7f-49b9-b658-24af318160cd

📥 Commits

Reviewing files that changed from the base of the PR and between e91b66e and 8792875.

⛔ Files ignored due to path filters (1)
  • README.md is excluded by !*.md
📒 Files selected for processing (36)
  • .agents/skills/ade-perf-lanes/SKILL.md
  • apps/desktop/src/main/services/chat/agentChatService.test.ts
  • apps/desktop/src/main/services/chat/agentChatService.ts
  • apps/desktop/src/main/services/ipc/registerIpc.ts
  • apps/desktop/src/main/services/localRuntime/localRuntimeConnectionPool.ts
  • apps/desktop/src/main/services/pty/ptyService.ts
  • apps/desktop/src/main/services/sessions/sessionService.test.ts
  • apps/desktop/src/main/services/sessions/sessionService.ts
  • apps/desktop/src/main/services/state/kvDb.ts
  • apps/desktop/src/preload/global.d.ts
  • apps/desktop/src/preload/preload.ts
  • apps/desktop/src/renderer/browserMock.ts
  • apps/desktop/src/renderer/components/app/TopBar.test.tsx
  • apps/desktop/src/renderer/components/app/TopBar.tsx
  • apps/desktop/src/renderer/components/lanes/CommitTimeline.test.tsx
  • apps/desktop/src/renderer/components/lanes/CommitTimeline.tsx
  • apps/desktop/src/renderer/components/lanes/LaneGitActionsPane.test.tsx
  • apps/desktop/src/renderer/components/lanes/LaneGitActionsPane.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/lanes/useLaneWorkSessions.test.ts
  • apps/desktop/src/renderer/components/lanes/useLaneWorkSessions.ts
  • apps/desktop/src/renderer/components/terminals/TerminalView.test.tsx
  • apps/desktop/src/renderer/components/terminals/TerminalView.tsx
  • apps/desktop/src/renderer/components/terminals/WorkViewArea.test.tsx
  • apps/desktop/src/renderer/components/terminals/WorkViewArea.tsx
  • apps/desktop/src/renderer/components/terminals/useWorkSessions.test.ts
  • apps/desktop/src/renderer/components/terminals/useWorkSessions.ts
  • apps/desktop/src/renderer/components/ui/PaneTilingLayout.tsx
  • apps/desktop/src/renderer/lib/resourcePressure.ts
  • apps/desktop/src/renderer/lib/sessionListCache.test.ts
  • apps/desktop/src/renderer/lib/sessionListCache.ts
  • apps/desktop/src/shared/ipc.ts
  • apps/desktop/src/shared/types/core.ts
  • apps/desktop/src/shared/types/sessions.ts
👮 Files not reviewed due to content moderation or server errors (1)
  • apps/desktop/src/main/services/chat/agentChatService.test.ts

Comment thread apps/desktop/src/main/services/ipc/registerIpc.ts
Comment thread apps/desktop/src/main/services/sessions/sessionService.test.ts Outdated
Comment thread apps/desktop/src/renderer/components/lanes/LanesPage.tsx
Comment thread apps/desktop/src/renderer/components/lanes/LanesPage.tsx Outdated
Comment thread apps/desktop/src/renderer/lib/resourcePressure.ts
Comment thread apps/desktop/src/renderer/lib/sessionListCache.ts
@arul28 arul28 merged commit 3e4605a into main Jun 2, 2026
28 checks passed
@arul28 arul28 deleted the autoresearch/lanes-lanes-20260531-1421 branch June 3, 2026 06:06
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