Skip to content

feat: terminal sessions, file watcher, PTY reattach, settings, MCP standalone chat#145

Merged
arul28 merged 3 commits intomainfrom
quick-fixes-2
Apr 9, 2026
Merged

feat: terminal sessions, file watcher, PTY reattach, settings, MCP standalone chat#145
arul28 merged 3 commits intomainfrom
quick-fixes-2

Conversation

@arul28
Copy link
Copy Markdown
Owner

@arul28 arul28 commented Apr 9, 2026

Summary

  • Terminal session management: Persisted work view state, collapsible session groups with sticky headers, redesigned session cards (status + preview + tool type), view mode toggle (tabs/grid)
  • File watcher overhaul: Ref-counted chokidar subscriptions with dual-mode search indexes, external change sync for open tabs, tree refresh queue cap
  • PTY reattach & resume: pty.create accepts existing sessionId for session reattach, transcript continuation in append mode, best-effort resume target backfill from transcript tail
  • Terminal preferences: Font size, line height, and scrollback configurable via Settings > General, persisted to localStorage, applied across all terminal surfaces
  • MCP standalone chat filtering: Coordinator and spawn_agent tools hidden from standalone chat sessions
  • ChatTerminalDrawer simplification: Rewrote to reuse shared TerminalView component instead of managing raw xterm instances
  • Code cleanup: Dead code removal, deduplication, accessibility fixes (<label htmlFor>), consolidated imports, extracted repeated patterns

Test plan

  • Typecheck passes (desktop, mcp-server, web)
  • Lint passes (desktop — 0 errors)
  • Desktop tests pass (3,710 tests across 8 shards)
  • MCP server tests pass (133 tests)
  • All apps build successfully
  • Doc validation passes (74 files)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Terminal preferences (font size, line height, scrollback) with persistence
    • Option to include ignored files in watch / quick-open / search
    • Session reattach support for resuming tracked sessions
  • UI Improvements

    • Sticky, collapsible section headers; session preview and compact relative times
    • Terminal rendering now follows saved preferences; file view simplified (dotfiles toggle removed)
  • Bug Fixes

    • More robust file-watching/indexing and project-scoped session caching
  • Tests

    • New integration/unit tests for ignored-files, watcher modes, terminals, and resume flows

…andalone chat

Overhaul terminal session management with persisted work view state,
collapsible session groups, session card redesign, and view mode toggle.
Refactor file watcher to use ref-counted subscriptions with dual-mode
search indexes. Add PTY session reattach and transcript resume. Introduce
terminal preferences (font size, line height, scrollback) in settings.
Hide coordinator tools from standalone MCP chat sessions. Simplify
ChatTerminalDrawer to reuse shared TerminalView. Code cleanup: dead code
removal, deduplication, accessibility fixes across services and components.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel bot commented Apr 9, 2026

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

Project Deployment Actions Updated (UTC)
ade Ready Ready Preview, Comment Apr 9, 2026 8:13pm

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 9, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 5e124bcc-5f38-43de-8aa5-b59cfc9eb6a9

📥 Commits

Reviewing files that changed from the base of the PR and between 2aa8fed and 5173ccd.

📒 Files selected for processing (1)
  • apps/desktop/src/renderer/state/appStore.ts

📝 Walkthrough

Walkthrough

Adds an includeIgnored mode across file indexing/watching, implements mode-aware workspace indexes and watcher refcounts; introduces PTY session reattach and deferred transcript post-processing; persists terminal preferences and work-view collapsed sections; refactors terminal rendering and several UI components; and updates/extends many tests and utilities.

Changes

Cohort / File(s) Summary
File indexing & watching
apps/desktop/src/main/services/files/fileSearchIndexService.ts, apps/desktop/src/main/services/files/fileWatcherService.ts, apps/desktop/src/main/services/files/fileWatcherService.test.ts, apps/desktop/src/main/services/files/fileService.ts, apps/desktop/src/main/services/files/fileService.test.ts, apps/desktop/src/shared/types/files.ts
Introduce includeIgnored mode and mode-specific workspace indexes; pass includeIgnored into shouldIgnore callbacks; make watcher subscriptions and invalidation mode-aware; add lifecycle/refcounting and tests asserting .ade/.git behavior.
Files UI and sync
apps/desktop/src/renderer/components/files/FilesPage.tsx, apps/desktop/src/renderer/components/files/FilesPage.test.tsx
Remove dotfiles toggle, normalize paths, always include ignored entries for listing/watching/search/quick-open; replace refresh batching with bounded queued parent-refreshes; add clean-tab-from-disk sync logic and related tests.
PTY / session lifecycle
apps/desktop/src/main/services/pty/ptyService.ts, apps/desktop/src/main/services/pty/ptyService.test.ts, apps/desktop/src/main/services/sessions/sessionService.ts, apps/desktop/src/main/services/sessions/sessionService.test.ts
Add reattach session API and reattach flow in PTY creation; defer transcript finalization and schedule post-close resume-target backfill + summarization; add tests for reattach flows and transcript-backed resume commands.
Terminal rendering & preferences
apps/desktop/src/renderer/components/terminals/TerminalView.tsx, apps/desktop/src/renderer/components/terminals/TerminalView.test.tsx, apps/desktop/src/renderer/components/settings/GeneralSection.tsx, apps/desktop/src/renderer/state/appStore.ts, apps/desktop/src/renderer/state/appStore.test.ts
Add persisted terminalPreferences (fontSize, lineHeight, scrollback) with normalization and persistence; UI controls in settings; apply preferences to xterm runtimes and expose DEFAULT_TERMINAL_PREFERENCES.
Terminal UI & session lists
apps/desktop/src/renderer/components/terminals/SessionCard.tsx, apps/desktop/src/renderer/components/terminals/SessionListPane.tsx, apps/desktop/src/renderer/components/terminals/WorkViewArea.tsx, apps/desktop/src/renderer/components/terminals/TerminalsPage.tsx, apps/desktop/src/renderer/components/terminals/useWorkSessions.ts, apps/desktop/src/renderer/components/terminals/useWorkSessions.test.ts
Replace status bucketing with sticky collapsible section headers; add workCollapsedSectionIds and toggle handlers; wire collapse state through hooks/pages; style/layout adjustments and updated tests.
Chat terminal & drawer refactor
apps/desktop/src/renderer/components/chat/ChatTerminalDrawer.tsx, apps/desktop/src/renderer/components/chat/AgentChatPane.tsx, apps/desktop/src/renderer/components/chat/AgentChatPane.submit.test.tsx
Remove in-component xterm lifecycle and lazy-load; delegate rendering to TerminalView via ptyId/sessionId; remove sessionId prop usage from AgentChatPane and add PTY mocks for tests.
CLI resume command & signals
apps/desktop/src/renderer/components/terminals/cliLaunch.ts, apps/desktop/src/renderer/components/terminals/cliLaunch.test.ts, apps/desktop/src/main/utils/terminalSessionSignals.ts, apps/desktop/src/main/utils/terminalSessionSignals.test.ts
Make resume flag/keyword unconditional and allow optional target ID; extend parsers to accept additional flag patterns; update builders and tests for optional-target behavior.
Utilities & caching
apps/desktop/src/renderer/lib/format.ts, apps/desktop/src/renderer/lib/format.test.ts, apps/desktop/src/renderer/lib/sessionListCache.ts, apps/desktop/src/renderer/lib/sessionListCache.test.ts, apps/desktop/src/renderer/lib/sessions.ts, apps/desktop/src/renderer/lib/sessions.test.ts
Add relativeTimeCompact, make session-list cache partition by project root, add shortToolTypeLabel; add/adjust tests validating outputs and cache isolation.
Misc tests and small changes
apps/desktop/src/renderer/components/files/*, apps/desktop/src/renderer/components/terminals/*, apps/mcp-server/*, apps/desktop/src/renderer/components/chat/*
Numerous test additions/adjustments (watcher, terminal, session, files, MCP server) and small runtime/test harness changes (fs stream mock, ADE PTY mocks, Monaco editor test helpers).
MCP server standalone-chat gating
apps/mcp-server/src/mcpServer.ts, apps/mcp-server/src/mcpServer.test.ts
Detect standalone-chat identity and hide/deny coordinator/spawn tools for standalone-chat callers; filter tools/list and reject hidden tool invocations with method-not-found error; add tests.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

desktop, mcp

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.41% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main changes: terminal sessions, file watcher, PTY reattach, settings, and MCP standalone chat. It is concise, specific, and directly related to the changeset.

✏️ 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 quick-fixes-2

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.

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: 10

Caution

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

⚠️ Outside diff range comments (4)
apps/desktop/src/main/services/files/fileService.ts (1)

123-128: ⚠️ Potential issue | 🟠 Major

EPIPE not fully caught—stdin error event is unhandled.

The pipeline failure indicates an EPIPE error during child.stdin.write. Node.js streams emit errors asynchronously via the 'error' event rather than throwing synchronously. The current try/catch only handles synchronous throws.

🐛 Proposed fix to handle stdin errors
+    child.stdin.on("error", () => {
+      // Ignore write errors (EPIPE when git exits early)
+    });
+
     try {
       child.stdin.write(`${args.paths.join("\n")}\n`);
       child.stdin.end();
     } catch {
       finish(new Set<string>());
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/main/services/files/fileService.ts` around lines 123 - 128,
The try/catch around child.stdin.write doesn't catch asynchronous stream errors
like EPIPE—attach an 'error' handler to child.stdin (and optionally to child) to
call finish(new Set<string>()) when an error occurs, and remove the handler
after successful write/close; keep the existing synchronous try/catch for
immediate throws but ensure you subscribe to child.stdin.on('error', ...) before
writing and clean up the listener after child.stdin.end() or on success to avoid
leaks (refer to child.stdin, child, args.paths, and finish).
apps/desktop/src/renderer/components/terminals/WorkViewArea.tsx (1)

486-506: ⚠️ Potential issue | 🟡 Minor

Expose the group’s collapse state to assistive tech.

This button toggles a disclosure, but it never reports whether the section is expanded or collapsed. Add aria-expanded={!group.collapsed} and, if possible, aria-controls pointing at the session container so screen-reader users can tell whether the group is open.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/renderer/components/terminals/WorkViewArea.tsx` around lines
486 - 506, The toggle button for a group (the element that calls
toggleTabGroupCollapsed(group.id)) currently doesn't expose the disclosure
state; add aria-expanded={!group.collapsed} to that button and set aria-controls
to the id of the session container (e.g. ensure the session list element uses a
stable id based on group.id like `session-container-${group.id}` or an existing
unique id) so assistive tech can read whether the group is open; also add/create
that id on the session container component that renders group.sessions to match
aria-controls.
apps/desktop/src/renderer/components/terminals/useWorkSessions.ts (1)

878-894: ⚠️ Potential issue | 🟠 Major

Treat the post-resume refresh as best-effort.

At this point the PTY has already been reattached successfully. If the forced refresh throws, the function exits before selecting/focusing the resumed session, leaving a live session running but not surfaced in the UI. launchPtySession() already handles refresh failure gracefully; resume should do the same.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/renderer/components/terminals/useWorkSessions.ts` around
lines 878 - 894, The forced refresh after reattaching the PTY should be
best-effort: wrap the await refresh({ showLoading: false, force: true }) call in
a try/catch (or otherwise handle rejection) so any thrown error is
swallowed/logged and does not abort the rest of the flow; ensure
invalidateSessionListCache() still runs and that selectLane(session.laneId),
focusSession(resumed.sessionId) and setActiveItemId(resumed.sessionId) always
execute after window.ade.pty.create(...) completes successfully (use the resumed
variable) even if refresh fails.
apps/desktop/src/renderer/state/appStore.ts (1)

464-517: ⚠️ Potential issue | 🟠 Major

Move full-map persistence off the interaction hot path.

Both setters now stringify and write the entire work-view payload on every state update. These setters are used for normal tab/select/close interactions, so this adds synchronous storage I/O to routine clicks in the renderer. Persist this on a debounce/idle boundary, or batch only the final state after a burst of updates.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/renderer/state/appStore.ts` around lines 464 - 517, The
setters setWorkViewState and setLaneWorkViewState are calling
persistWorkViewState synchronously on every update which causes blocking sync
storage I/O on common UI interactions; change them to enqueue the new
workViewByProject / laneWorkViewByScope into in-memory store state only and
defer calling persistWorkViewState to a debounced/idle flush (e.g. use a
module-level debounce timer or requestIdleCallback) that writes the combined
payload once after a burst of updates; keep the existing updated object
construction logic in setWorkViewState and setLaneWorkViewState but remove the
direct persistWorkViewState calls and instead trigger the single flush function
that calls persistWorkViewState with { workViewByProject, laneWorkViewByScope }
when the timer/idle callback fires.
🧹 Nitpick comments (3)
apps/desktop/src/renderer/lib/sessions.ts (1)

79-90: Consider centralizing tool-type label mappings to prevent drift.

shortToolTypeLabel adds another mapping table alongside existing label formatters. A shared map/helper would reduce inconsistency risk as new tool types are added.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/renderer/lib/sessions.ts` around lines 79 - 90,
shortToolTypeLabel currently implements its own if-chain mapping for tool type
labels which can drift from other label formatters; refactor by extracting a
shared mapping lookup (e.g., a central TOOL_TYPE_LABELS map and a helper like
getToolTypeLabel(toolType: string | null | undefined)) and update
shortToolTypeLabel to call that helper (falling back to the existing
replace(/-/g, " ") behavior). Replace the hardcoded startsWith/equals logic in
shortToolTypeLabel with a single map lookup and ensure other label formatters in
the codebase use the same helper to keep mappings centralized and consistent.
apps/desktop/src/renderer/components/terminals/SessionCard.tsx (1)

172-183: Improve keyboard discoverability of hover actions.

Consider adding group-focus-within:opacity-100 (container) and explicit focus-visible ring styles on these buttons so keyboard users can reliably discover and track focus on hidden-on-hover controls.

♿ Suggested accessibility-focused refinement
-      <div className="absolute right-1.5 top-1 flex items-center gap-0.5 opacity-0 transition-opacity group-hover:opacity-100">
+      <div className="absolute right-1.5 top-1 flex items-center gap-0.5 opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100">
...
-          className="inline-flex items-center justify-center h-5 w-5 rounded-full border border-white/[0.08] bg-white/[0.06] text-muted-fg/60 hover:text-fg hover:bg-white/[0.10] transition-colors"
+          className="inline-flex items-center justify-center h-5 w-5 rounded-full border border-white/[0.08] bg-white/[0.06] text-muted-fg/60 hover:text-fg hover:bg-white/[0.10] focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-accent/70 transition-colors"
...
-            className="inline-flex items-center gap-0.5 px-1.5 py-0.5 rounded border border-white/[0.08] bg-white/[0.06] text-muted-fg/60 hover:text-fg hover:bg-white/[0.10] transition-colors text-[10px] font-medium"
+            className="inline-flex items-center gap-0.5 px-1.5 py-0.5 rounded border border-white/[0.08] bg-white/[0.06] text-muted-fg/60 hover:text-fg hover:bg-white/[0.10] focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-accent/70 transition-colors text-[10px] font-medium"

As per coding guidelines apps/desktop/src/**: Electron desktop app — check for IPC security, proper main/renderer process separation, and React best practices.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/renderer/components/terminals/SessionCard.tsx` around lines
172 - 183, The hover-only action buttons in SessionCard need keyboard
discoverability: add a container-level utility such as group and
group-focus-within:opacity-100 to the wrapper around the action buttons so they
become visible when focused via keyboard, and add explicit focus-visible styles
(e.g., a visible ring outline) to both the Info button (the element calling
onInfoClick) and the Resume button (the button that uses canResume and checks
resumingSessionId) so keyboard users can see and track focus; update the
className strings for those buttons to include focus-visible ring utilities and
ensure the parent container includes the group and group-focus-within classes.
apps/desktop/src/main/services/files/fileSearchIndexService.ts (1)

144-148: Potential inconsistency: node_modules indexed but not watched.

When includeIgnored: true, this function allows node_modules to be indexed (line 146 returns false). However, fileWatcherService.ts always ignores node_modules via ALWAYS_IGNORED_PATTERNS, meaning changes in node_modules won't trigger onFileChanged.

This creates a stale index scenario: files in node_modules are indexed initially but never updated on changes.

Consider aligning the behavior—either always skip node_modules in indexing, or add a comment clarifying the intentional divergence:

♻️ Option A: Always skip node_modules in indexer
 const shouldSkipDirectoryName = (name: string, includeIgnored: boolean): boolean => {
   if (name === ".git") return true;
-  if (!includeIgnored && name === "node_modules") return true;
+  if (name === "node_modules") return true;
   return false;
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/main/services/files/fileSearchIndexService.ts` around lines
144 - 148, The indexer currently may include node_modules when includeIgnored is
true, but fileWatcherService always ignores node_modules, causing stale entries;
update the shouldSkipDirectoryName function so that it always returns true for
"node_modules" (remove the includeIgnored conditional for that name) to align
indexing with ALWAYS_IGNORED_PATTERNS, and add/update a short comment in
fileSearchIndexService.ts near shouldSkipDirectoryName explaining that
node_modules is intentionally always skipped to match fileWatcherService
behavior; also run/adjust any tests or call sites that assume node_modules can
be indexed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/desktop/src/main/services/files/fileService.test.ts`:
- Around line 53-92: The test fails with EPIPE because fileService uses git
check-ignore in non-git temp dirs; fix by initializing a git repo in the temp
root before creating the service (e.g., run a git init in the temp root created
with fs.mkdtempSync) or alternatively stub/mock out git calls in the
FileService; update the test around createLaneServiceStub/rootPath and
createFileService so the temp directory is a valid git repo before calling
service.quickOpen and service.searchText.

In `@apps/desktop/src/renderer/components/chat/ChatTerminalDrawer.tsx`:
- Around line 176-190: The close affordance inside ChatTerminalDrawer.tsx should
be a real focusable button sibling to the tab instead of a span with
role="button" and tabIndex={-1}; replace the inner <span> close control with a
proper <button> element (keep using closeTab(tab.id) for the onClick and onKey
handling), move stopPropagation to the button's onClick, add an accessible label
(e.g., aria-label="Close tab"), ensure it is a sibling of the tab content (not
nested) so keyboard users can tab to it, and preserve the existing classes/hover
styles (e.g., "ml-0.5 text-white/30 ...") and any group-hover behavior.
- Around line 90-103: Auto-create is racing with the empty-state close and
causing PTY leaks and retry loops; add a guard ref so the auto-create effect
runs only on the initial open (not after the user closed the last tab) and avoid
re-triggering on failed pty.create calls. Concretely, introduce a ref like
autoCreateDoneRef and in the first useEffect (the one that calls createTab)
require !autoCreateDoneRef.current and set it true after a successful createTab;
keep the existing checks for open, creatingTab and tabs.length, and do not clear
autoCreateDoneRef when hadTabsRef.current flips during user-initiated close so
the effect will not re-run while onToggle/closing occurs. This uses the existing
symbols createTab, creatingTab, open, tabs.length, hadTabsRef, and onToggle to
locate and implement the change.

In `@apps/desktop/src/renderer/components/terminals/useWorkSessions.test.ts`:
- Around line 12-25: The tests share a mutable fakeAppStoreState initialized
only once via resetFakeAppStoreState(), causing later describe blocks to inherit
state; ensure resetFakeAppStoreState() runs before each test (e.g., add a
top-level beforeEach that calls resetFakeAppStoreState()) or reinitialize
fakeAppStoreState inside each describe to make tests independent; update
references to fakeAppStoreState, resetFakeAppStoreState, and any spies
(focusSessionSpy, selectLaneSpy, setWorkViewStateSpy) so each test gets a fresh
store instance.

In `@apps/desktop/src/renderer/components/terminals/useWorkSessions.ts`:
- Around line 584-594: The effect on projectRoot currently clears
refreshQueuedRef.current without resolving its deferred, which can leave waiters
hanging; before setting refreshQueuedRef.current = null in the useEffect inside
useWorkSessions, detect if refreshQueuedRef.current exists and call its resolve
or reject (e.g. reject with a cancellation error or resolve with a sensible
value) to settle the promise, then clear it; ensure you update the logic around
refreshQueuedRef (and any callers awaiting the deferred) so they handle the
settled state correctly and avoid memory leaks or dangling waiters while keeping
the existing invalidateSessionListCache, setSessions, and refresh({ showLoading:
true, force: true }) behavior.

In `@apps/desktop/src/renderer/components/terminals/WorkViewArea.tsx`:
- Around line 646-678: The segmented control rendering in WorkViewArea uses
buttons mapped from the array but only conveys state with color; update the
mapped <button> (the one using viewMode and setViewMode) to include
type="button" and aria-pressed={active} so the control exposes the selected
state to keyboard and screen-reader users; keep the existing onClick, className,
title and styles, and use the local variables active, mode, icon, label as
currently used.

In `@apps/mcp-server/src/mcpServer.test.ts`:
- Around line 1092-1103: The assertion using
expect(names).not.toEqual(expect.arrayContaining([...])) is too weak; update the
test to assert each forbidden tool is absent individually by replacing that
arrayContaining check with per-tool assertions like
expect(names).not.toContain("<tool>") for each of the listed tools (use the same
pattern already used earlier in the file for names and not.toContain). Ensure
you reference the same variable names (names) and the exact forbidden tool
strings ("spawn_agent", "delegate_to_subagent", "delegate_parallel",
"report_status", "report_result", "get_worker_output", "read_mission_status",
"list_workers") so each is checked separately.

In `@apps/mcp-server/src/mcpServer.ts`:
- Around line 2517-2527: The predicate isStandaloneChatCaller and
isToolHiddenForStandaloneChat currently rely on caller-controlled fields
(missionId, stepId, attemptId) which can be injected; change the check to use
only server-authorized context (e.g., a server-validated flag or server-side
session fields such as callerCtx.serverVerifiedSessionType or
callerCtx.authorizedMissionId) or alternatively make initialize explicitly
reject missionId/stepId/attemptId for chat-only sessions; update
isStandaloneChatCaller to read that server-validated property instead of
missionId/stepId/attemptId and ensure isToolHiddenForStandaloneChat calls the
updated predicate so coordinator-tool paths remain blocked for true standalone
chat callers.
- Around line 1541-1544: The STANDALONE_CHAT_HIDDEN_TOOL_NAMES set currently
only contains "spawn_agent" plus AGENT_VISIBLE_COORDINATOR_TOOL_NAMES, but you
must hide the entire coordinator surface for standalone chats; replace its
construction to include all coordinator tool names (e.g., union
Object.keys(COORDINATOR_TOOL_SPECS) and "spawn_agent" or simply use
Object.keys(COORDINATOR_TOOL_SPECS)) so every coordinator tool is in
STANDALONE_CHAT_HIDDEN_TOOL_NAMES, and ensure the tools/list and tools/call code
paths that check role === "orchestrator" for standalone chat sessions use this
updated set to filter both listing and execution.

---

Outside diff comments:
In `@apps/desktop/src/main/services/files/fileService.ts`:
- Around line 123-128: The try/catch around child.stdin.write doesn't catch
asynchronous stream errors like EPIPE—attach an 'error' handler to child.stdin
(and optionally to child) to call finish(new Set<string>()) when an error
occurs, and remove the handler after successful write/close; keep the existing
synchronous try/catch for immediate throws but ensure you subscribe to
child.stdin.on('error', ...) before writing and clean up the listener after
child.stdin.end() or on success to avoid leaks (refer to child.stdin, child,
args.paths, and finish).

In `@apps/desktop/src/renderer/components/terminals/useWorkSessions.ts`:
- Around line 878-894: The forced refresh after reattaching the PTY should be
best-effort: wrap the await refresh({ showLoading: false, force: true }) call in
a try/catch (or otherwise handle rejection) so any thrown error is
swallowed/logged and does not abort the rest of the flow; ensure
invalidateSessionListCache() still runs and that selectLane(session.laneId),
focusSession(resumed.sessionId) and setActiveItemId(resumed.sessionId) always
execute after window.ade.pty.create(...) completes successfully (use the resumed
variable) even if refresh fails.

In `@apps/desktop/src/renderer/components/terminals/WorkViewArea.tsx`:
- Around line 486-506: The toggle button for a group (the element that calls
toggleTabGroupCollapsed(group.id)) currently doesn't expose the disclosure
state; add aria-expanded={!group.collapsed} to that button and set aria-controls
to the id of the session container (e.g. ensure the session list element uses a
stable id based on group.id like `session-container-${group.id}` or an existing
unique id) so assistive tech can read whether the group is open; also add/create
that id on the session container component that renders group.sessions to match
aria-controls.

In `@apps/desktop/src/renderer/state/appStore.ts`:
- Around line 464-517: The setters setWorkViewState and setLaneWorkViewState are
calling persistWorkViewState synchronously on every update which causes blocking
sync storage I/O on common UI interactions; change them to enqueue the new
workViewByProject / laneWorkViewByScope into in-memory store state only and
defer calling persistWorkViewState to a debounced/idle flush (e.g. use a
module-level debounce timer or requestIdleCallback) that writes the combined
payload once after a burst of updates; keep the existing updated object
construction logic in setWorkViewState and setLaneWorkViewState but remove the
direct persistWorkViewState calls and instead trigger the single flush function
that calls persistWorkViewState with { workViewByProject, laneWorkViewByScope }
when the timer/idle callback fires.

---

Nitpick comments:
In `@apps/desktop/src/main/services/files/fileSearchIndexService.ts`:
- Around line 144-148: The indexer currently may include node_modules when
includeIgnored is true, but fileWatcherService always ignores node_modules,
causing stale entries; update the shouldSkipDirectoryName function so that it
always returns true for "node_modules" (remove the includeIgnored conditional
for that name) to align indexing with ALWAYS_IGNORED_PATTERNS, and add/update a
short comment in fileSearchIndexService.ts near shouldSkipDirectoryName
explaining that node_modules is intentionally always skipped to match
fileWatcherService behavior; also run/adjust any tests or call sites that assume
node_modules can be indexed.

In `@apps/desktop/src/renderer/components/terminals/SessionCard.tsx`:
- Around line 172-183: The hover-only action buttons in SessionCard need
keyboard discoverability: add a container-level utility such as group and
group-focus-within:opacity-100 to the wrapper around the action buttons so they
become visible when focused via keyboard, and add explicit focus-visible styles
(e.g., a visible ring outline) to both the Info button (the element calling
onInfoClick) and the Resume button (the button that uses canResume and checks
resumingSessionId) so keyboard users can see and track focus; update the
className strings for those buttons to include focus-visible ring utilities and
ensure the parent container includes the group and group-focus-within classes.

In `@apps/desktop/src/renderer/lib/sessions.ts`:
- Around line 79-90: shortToolTypeLabel currently implements its own if-chain
mapping for tool type labels which can drift from other label formatters;
refactor by extracting a shared mapping lookup (e.g., a central TOOL_TYPE_LABELS
map and a helper like getToolTypeLabel(toolType: string | null | undefined)) and
update shortToolTypeLabel to call that helper (falling back to the existing
replace(/-/g, " ") behavior). Replace the hardcoded startsWith/equals logic in
shortToolTypeLabel with a single map lookup and ensure other label formatters in
the codebase use the same helper to keep mappings centralized and consistent.
🪄 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: 76d82c37-a830-453e-b3b3-1a8fec2828e2

📥 Commits

Reviewing files that changed from the base of the PR and between 6a4eba0 and 0f38a14.

⛔ Files ignored due to path filters (7)
  • docs/ORCHESTRATOR_OVERHAUL.md is excluded by !docs/**
  • docs/architecture/AI_INTEGRATION.md is excluded by !docs/**
  • docs/features/AGENTS.md is excluded by !docs/**
  • docs/features/CHAT.md is excluded by !docs/**
  • docs/features/FILES_AND_EDITOR.md is excluded by !docs/**
  • docs/features/ONBOARDING_AND_SETTINGS.md is excluded by !docs/**
  • docs/features/TERMINALS_AND_SESSIONS.md is excluded by !docs/**
📒 Files selected for processing (40)
  • apps/desktop/src/main/services/files/fileSearchIndexService.ts
  • apps/desktop/src/main/services/files/fileService.test.ts
  • apps/desktop/src/main/services/files/fileService.ts
  • apps/desktop/src/main/services/files/fileWatcherService.test.ts
  • apps/desktop/src/main/services/files/fileWatcherService.ts
  • apps/desktop/src/main/services/pty/ptyService.test.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/utils/terminalSessionSignals.test.ts
  • apps/desktop/src/main/utils/terminalSessionSignals.ts
  • apps/desktop/src/renderer/components/chat/AgentChatPane.submit.test.tsx
  • apps/desktop/src/renderer/components/chat/AgentChatPane.tsx
  • apps/desktop/src/renderer/components/chat/ChatTerminalDrawer.tsx
  • apps/desktop/src/renderer/components/files/FilesPage.test.tsx
  • apps/desktop/src/renderer/components/files/FilesPage.tsx
  • apps/desktop/src/renderer/components/lanes/useLaneWorkSessions.ts
  • apps/desktop/src/renderer/components/settings/GeneralSection.tsx
  • apps/desktop/src/renderer/components/terminals/SessionCard.tsx
  • apps/desktop/src/renderer/components/terminals/SessionListPane.tsx
  • apps/desktop/src/renderer/components/terminals/TerminalView.test.tsx
  • apps/desktop/src/renderer/components/terminals/TerminalView.tsx
  • apps/desktop/src/renderer/components/terminals/TerminalsPage.tsx
  • apps/desktop/src/renderer/components/terminals/WorkViewArea.tsx
  • apps/desktop/src/renderer/components/terminals/cliLaunch.test.ts
  • apps/desktop/src/renderer/components/terminals/cliLaunch.ts
  • apps/desktop/src/renderer/components/terminals/useWorkSessions.test.ts
  • apps/desktop/src/renderer/components/terminals/useWorkSessions.ts
  • apps/desktop/src/renderer/lib/format.test.ts
  • apps/desktop/src/renderer/lib/format.ts
  • apps/desktop/src/renderer/lib/sessionListCache.test.ts
  • apps/desktop/src/renderer/lib/sessionListCache.ts
  • apps/desktop/src/renderer/lib/sessions.test.ts
  • apps/desktop/src/renderer/lib/sessions.ts
  • apps/desktop/src/renderer/state/appStore.test.ts
  • apps/desktop/src/renderer/state/appStore.ts
  • apps/desktop/src/shared/types/files.ts
  • apps/desktop/src/shared/types/sessions.ts
  • apps/mcp-server/src/mcpServer.test.ts
  • apps/mcp-server/src/mcpServer.ts
💤 Files with no reviewable changes (1)
  • apps/desktop/src/renderer/components/chat/AgentChatPane.tsx

Comment thread apps/desktop/src/main/services/files/fileService.test.ts
Comment on lines +161 to +168
parts.push("--resume");
if (targetId.length) parts.push(targetId);
return parts.join(" ");
}

const parts = ["codex", "--no-alt-screen", ...permissionModeToCodexFlags(permissionMode)];
if (targetId.length) parts.push("resume", targetId);
parts.push("resume");
if (targetId.length) parts.push(targetId);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Teach transcript extraction about the new permission-aware resume commands.

buildTrackedCliResumeCommand() now produces strings like claude --permission-mode default --resume and codex --no-alt-screen --full-auto resume, but extractResumeCommandFromOutput() still uses the regexes at Lines 12-13, which only match when --resume/resume comes immediately after the executable. Any transcript-tail backfill that sees the rebuilt command form will miss it and fall back to the generic picker instead of recovering the concrete resume command.

Comment thread apps/desktop/src/renderer/components/chat/ChatTerminalDrawer.tsx
Comment thread apps/desktop/src/renderer/components/chat/ChatTerminalDrawer.tsx Outdated
Comment thread apps/desktop/src/renderer/components/terminals/useWorkSessions.ts
Comment thread apps/desktop/src/renderer/components/terminals/WorkViewArea.tsx
Comment thread apps/mcp-server/src/mcpServer.test.ts Outdated
Comment thread apps/mcp-server/src/mcpServer.ts
Comment thread apps/mcp-server/src/mcpServer.ts
… test isolation

- fileService: handle async EPIPE on child.stdin, git init in test temp dir
- fileSearchIndexService: always skip node_modules regardless of includeIgnored
- ChatTerminalDrawer: proper <button> for close tab, autoCreateDoneRef guard to prevent PTY leak
- useWorkSessions: resolve deferred on projectRoot change, best-effort PTY reattach refresh, test state isolation
- WorkViewArea/SessionCard: aria-pressed, aria-expanded, focus-visible keyboard styles
- mcpServer: hide all coordinator tools for standalone chat, use server-validated session flag instead of caller-controlled fields
- appStore: debounce persistWorkViewState to avoid blocking UI
- sessions.ts: extract TOOL_TYPE_LABELS map from if-chain

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/desktop/src/renderer/state/appStore.ts`:
- Around line 169-191: Pending debounced writes can race with immediate persists
and reintroduce stale data; ensure any immediate calls to persistWorkViewState
(from setWorkViewState and setLaneWorkViewState) first cancel the pending
debounced timer by checking and clearing _debouncePersistTimer (and setting it
to null) before performing the immediate persist, or alternatively call
clearTimeout(_debouncePersistTimer) and null it inside persistWorkViewState so
that debouncedPersistWorkViewState cannot later overwrite the freshly written
localStorage entry keyed by WORK_VIEW_STORAGE_KEY.
🪄 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: 9698b1d7-95fc-46b0-9d61-ad62446413ee

📥 Commits

Reviewing files that changed from the base of the PR and between 0f38a14 and 2aa8fed.

📒 Files selected for processing (12)
  • apps/desktop/src/main/services/files/fileSearchIndexService.ts
  • apps/desktop/src/main/services/files/fileService.test.ts
  • apps/desktop/src/main/services/files/fileService.ts
  • apps/desktop/src/renderer/components/chat/ChatTerminalDrawer.tsx
  • apps/desktop/src/renderer/components/terminals/SessionCard.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/lib/sessions.ts
  • apps/desktop/src/renderer/state/appStore.ts
  • apps/mcp-server/src/mcpServer.test.ts
  • apps/mcp-server/src/mcpServer.ts
✅ Files skipped from review due to trivial changes (2)
  • apps/desktop/src/main/services/files/fileService.test.ts
  • apps/desktop/src/renderer/components/chat/ChatTerminalDrawer.tsx
🚧 Files skipped from review as they are similar to previous changes (6)
  • apps/desktop/src/renderer/lib/sessions.ts
  • apps/desktop/src/renderer/components/terminals/useWorkSessions.test.ts
  • apps/desktop/src/renderer/components/terminals/WorkViewArea.tsx
  • apps/desktop/src/main/services/files/fileService.ts
  • apps/desktop/src/renderer/components/terminals/useWorkSessions.ts
  • apps/desktop/src/main/services/files/fileSearchIndexService.ts

Comment thread apps/desktop/src/renderer/state/appStore.ts
Prevents a stale debounced write from overwriting a fresh immediate
persist (e.g. from refreshLanes or project transitions).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@arul28 arul28 merged commit 3d6c578 into main Apr 9, 2026
22 checks passed
@arul28 arul28 deleted the quick-fixes-2 branch April 14, 2026 07:52
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