Skip to content

Automations fixes and lane-wide UX/runtime polish#321

Merged
arul28 merged 1 commit into
mainfrom
ade/automations-fixes-619117dc
May 19, 2026
Merged

Automations fixes and lane-wide UX/runtime polish#321
arul28 merged 1 commit into
mainfrom
ade/automations-fixes-619117dc

Conversation

@arul28
Copy link
Copy Markdown
Owner

@arul28 arul28 commented May 19, 2026

Summary

  • Automations module fixes (planner, service, rules editor, templates page, action row, executor config)
  • ADE CLI TUI lane chat-count surfacing, subagent pane updates, project scope adjustments
  • Desktop chat/mission/PTY/IPC/runtime updates across renderer + main
  • Docs refresh across architecture, automations, chat, missions, onboarding, sync, terminals

Test plan

  • CI green across all required checks
  • No regressions in automations execution path
  • Chat, mission, and PTY flows still operate end-to-end

@copilot please review.

Greptile Summary

This PR delivers a broad platform polish pass: multi-project tab support (per-project Zustand stores, stale-while-revalidate lane/session caches, restored selections on tab switch), subagent drill-in with per-runtime transcript fetching, terminal replay mode for disposed chat-CLI sessions, Codex codexFastMode propagation through automations, PTY auto-reattach on dead chat-CLI terminals, and a runtime compatibility guard that preserves live work instead of force-shutting mismatched services.

  • Multi-project tabs (appStore.ts, App.tsx): singleton Zustand store replaced by per-project stores with an AppStoreProvider context; ProjectTabHost mounts up to 8 project surfaces simultaneously, keeping agent runtimes alive across switches.
  • Subagent UX (chatSubagents.ts, agentChatService.ts): new shared snapshot builder, Agent #N Codex labelling, Task-tool input stashing for richer agentType enrichment, and getSubagentTranscript IPC for drill-in view.
  • Terminal replay (TerminalView.tsx): disposed chat-CLI sessions load a flattened ANSI transcript with alt-screen sequences stripped; disposeStaleRuntimes narrowed to avoid evicting runtimes for other open project tabs.

Confidence Score: 4/5

The core chat, mission, and PTY flows are additive on top of an established architecture; the multi-project store refactor has deliberate fallbacks and good test coverage.

The new per-project store model correctly routes preference updates through the root store. Two areas warrant attention before the tab-switching feature sees wide use: disposeStaleRuntimes no longer evicts xterm runtimes for closed project tabs (memory accumulation with heavy cycling), and the fallback cacheKey in sessionListCache reads from the root store, trapping future callers that omit the projectRoot option. Neither causes immediate user-visible breakage on the happy path.

apps/desktop/src/renderer/components/terminals/TerminalView.tsx (stale-runtime eviction gap) and apps/desktop/src/renderer/lib/sessionListCache.ts (root-store fallback in cacheKey).

Important Files Changed

Filename Overview
apps/desktop/src/renderer/state/appStore.ts Migrates from a singleton Zustand store to a per-project store model with AppStoreProvider context. Adds lane/session/project-info caches and stale-while-revalidate logic for instant project tab switching.
apps/desktop/src/renderer/components/app/App.tsx Replaces single-route layout with multi-project ProjectTabHost + per-project ProjectSurface components, each with its own Zustand store and inert attribute management.
apps/desktop/src/shared/chatSubagents.ts New shared module centralising subagent snapshot building. One unexported constant (SUBAGENT_PANE_TABLE_START_LINE) is dead code.
apps/desktop/src/main/services/chat/agentChatService.ts Adds subagent transcript fetching, Task-tool input stashing, and Codex Agent #N labelling. The codexAgentIndexByTurn clear on interruption is asymmetric with the per-turn delete at completion.
apps/desktop/src/renderer/components/terminals/TerminalView.tsx Adds terminal replay mode for disposed chat-CLI sessions. The disposeStaleRuntimes narrowing leaves no cleanup path for runtimes from unmounted project tabs.
apps/desktop/src/main/services/pty/ptyService.ts Adds reattachChatCli with single-flight dedup; writeTerminal now auto-reattaches dead chat-CLI PTYs. The async upgrade is backward-compatible.
apps/desktop/src/main/services/localRuntime/localRuntimeConnectionPool.ts Replaces shutdownRuntimeClient with closeRuntimeClient on version mismatch, intentionally leaving incompatible runtimes alive to preserve user work.
apps/desktop/src/main/services/automations/automationService.ts Adds codexFastMode propagation to automation execution paths, correctly gated on providerGroup and modelSupportsFastMode.
apps/desktop/src/renderer/lib/sessionListCache.ts Adds optional projectRoot cache-key override. The fallback cacheKey() still reads from the singleton root store, giving wrong keys for non-active project tabs when callers omit the option.

Comments Outside Diff (2)

  1. apps/desktop/src/renderer/lib/sessionListCache.ts, line 24-31 (link)

    P2 Stale project-root in fallback cache key

    cacheKey always calls useAppStore.getState(), which is hard-wired to rootAppStore. When a ProjectSurface for a non-active project tab calls listSessionsCached without the new options.projectRoot argument, the key will contain the globally-active project root rather than the tab's own project root — all tabs hitting this path share a single cache bucket. useWorkSessions passes projectRoot explicitly so the hot path is safe, but any caller that omits the option will silently get sessions for the wrong project.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: apps/desktop/src/renderer/lib/sessionListCache.ts
    Line: 24-31
    
    Comment:
    **Stale project-root in fallback cache key**
    
    `cacheKey` always calls `useAppStore.getState()`, which is hard-wired to `rootAppStore`. When a `ProjectSurface` for a non-active project tab calls `listSessionsCached` without the new `options.projectRoot` argument, the key will contain the globally-active project root rather than the tab's own project root — all tabs hitting this path share a single cache bucket. `useWorkSessions` passes `projectRoot` explicitly so the hot path is safe, but any caller that omits the option will silently get sessions for the wrong project.
    
    How can I resolve this? If you propose a fix, please make it concise.

    Fix in Claude Code

  2. apps/desktop/src/renderer/components/terminals/TerminalView.tsx, line 547-555 (link)

    P2 Runtimes from closed project tabs are never evicted

    Before this PR, disposeStaleRuntimes tore down any non-live runtime whose projectRoot differed from the active one. The new condition requires runtime.projectRoot === activeProjectRoot, so runtimes from other project roots are silently skipped. When a tab is pruned from mountedProjects and its ProjectSurface unmounts, the entries in the module-level runtimeCache Map are never scheduled for disposal. Replay-mode runtimes with REPLAY_SCROLLBACK_LINES = 100_000 can accumulate meaningfully over extended sessions.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: apps/desktop/src/renderer/components/terminals/TerminalView.tsx
    Line: 547-555
    
    Comment:
    **Runtimes from closed project tabs are never evicted**
    
    Before this PR, `disposeStaleRuntimes` tore down any non-live runtime whose `projectRoot` differed from the active one. The new condition requires `runtime.projectRoot === activeProjectRoot`, so runtimes from other project roots are silently skipped. When a tab is pruned from `mountedProjects` and its `ProjectSurface` unmounts, the entries in the module-level `runtimeCache` Map are never scheduled for disposal. Replay-mode runtimes with `REPLAY_SCROLLBACK_LINES = 100_000` can accumulate meaningfully over extended sessions.
    
    How can I resolve this? If you propose a fix, please make it concise.

    Fix in Claude Code

Fix All in Claude Code

Prompt To Fix All With AI
Fix the following 4 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 4
apps/desktop/src/renderer/lib/sessionListCache.ts:24-31
**Stale project-root in fallback cache key**

`cacheKey` always calls `useAppStore.getState()`, which is hard-wired to `rootAppStore`. When a `ProjectSurface` for a non-active project tab calls `listSessionsCached` without the new `options.projectRoot` argument, the key will contain the globally-active project root rather than the tab's own project root — all tabs hitting this path share a single cache bucket. `useWorkSessions` passes `projectRoot` explicitly so the hot path is safe, but any caller that omits the option will silently get sessions for the wrong project.

### Issue 2 of 4
apps/desktop/src/renderer/components/terminals/TerminalView.tsx:547-555
**Runtimes from closed project tabs are never evicted**

Before this PR, `disposeStaleRuntimes` tore down any non-live runtime whose `projectRoot` differed from the active one. The new condition requires `runtime.projectRoot === activeProjectRoot`, so runtimes from other project roots are silently skipped. When a tab is pruned from `mountedProjects` and its `ProjectSurface` unmounts, the entries in the module-level `runtimeCache` Map are never scheduled for disposal. Replay-mode runtimes with `REPLAY_SCROLLBACK_LINES = 100_000` can accumulate meaningfully over extended sessions.

### Issue 3 of 4
apps/desktop/src/shared/chatSubagents.ts:45-48
`SUBAGENT_PANE_TABLE_START_LINE` is defined but never referenced in this file and is not exported. The comment references a mouse-click row mapper that does not exist here. Either export the constant for the TUI consumer or remove it.

```suggestion
// Vertical offset of the first selectable roster row in the rendered chat-info
// pane (header + status + plan + goal occupy the preceding lines). Used only by
// the mouse-click → row mapper.
export const SUBAGENT_PANE_TABLE_START_LINE = 4;
```

### Issue 4 of 4
apps/desktop/src/main/services/chat/agentChatService.ts:12929-12932
**Turn-level Codex agent-index maps cleared globally on interruption**

`runtime.codexAgentIndexByTurn.delete(turnId)` correctly removes only the finished turn at normal completion, but the interrupted-turn handler calls `runtime.codexAgentIndexByTurn.clear()`, removing every turn's index map at once. If parallel Codex collab agents span multiple concurrent turns, an interrupt in one turn erases counter state for all others — subsequent agents restart numbering from `#1` and may produce duplicate `Agent #N` labels.

Reviews (1): Last reviewed commit: "Automations fixes and lane-wide UX/runti..." | Re-trigger Greptile

Greptile also left 2 inline comments on this PR.

Ship the automations rework alongside related ADE CLI TUI, desktop chat,
PTY, IPC, runtime, and docs updates accumulated on this lane.

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

vercel Bot commented May 19, 2026

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
ade Ignored Ignored May 19, 2026 8:49am

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 19, 2026

Warning

Rate limit exceeded

@arul28 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 59 minutes and 24 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ae079ca7-95d0-4377-a227-f2557c2fcce5

📥 Commits

Reviewing files that changed from the base of the PR and between 049a79f and c07fe6f.

⛔ Files ignored due to path filters (11)
  • docs/ARCHITECTURE.md is excluded by !docs/**
  • docs/features/automations/README.md is excluded by !docs/**
  • docs/features/automations/triggers-and-actions.md is excluded by !docs/**
  • docs/features/chat/README.md is excluded by !docs/**
  • docs/features/chat/composer-and-ui.md is excluded by !docs/**
  • docs/features/chat/transcript-and-turns.md is excluded by !docs/**
  • docs/features/missions/README.md is excluded by !docs/**
  • docs/features/onboarding-and-settings/README.md is excluded by !docs/**
  • docs/features/sync-and-multi-device/ios-companion.md is excluded by !docs/**
  • docs/features/terminals-and-sessions/pty-and-processes.md is excluded by !docs/**
  • docs/features/terminals-and-sessions/ui-surfaces.md is excluded by !docs/**
📒 Files selected for processing (95)
  • apps/ade-cli/src/cli.ts
  • apps/ade-cli/src/services/projects/projectScope.test.ts
  • apps/ade-cli/src/services/projects/projectScope.ts
  • apps/ade-cli/src/tuiClient/app.tsx
  • apps/ade-cli/src/tuiClient/chatInfo.ts
  • apps/ade-cli/src/tuiClient/subagentPane.ts
  • apps/ade-cli/src/tuiClient/types.ts
  • apps/desktop/scripts/dev.cjs
  • apps/desktop/scripts/ensure-ade-cli-build.cjs
  • apps/desktop/src/main/main.ts
  • apps/desktop/src/main/services/adeActions/registry.ts
  • apps/desktop/src/main/services/appControl/appControlService.ts
  • apps/desktop/src/main/services/automations/automationPlannerService.ts
  • apps/desktop/src/main/services/automations/automationService.test.ts
  • apps/desktop/src/main/services/automations/automationService.ts
  • apps/desktop/src/main/services/builtInBrowser/builtInBrowserService.test.ts
  • apps/desktop/src/main/services/builtInBrowser/builtInBrowserService.ts
  • apps/desktop/src/main/services/chat/agentChatService.test.ts
  • apps/desktop/src/main/services/chat/agentChatService.ts
  • apps/desktop/src/main/services/config/projectConfigService.automationExecution.test.ts
  • apps/desktop/src/main/services/config/projectConfigService.ts
  • apps/desktop/src/main/services/ipc/registerIpc.ts
  • apps/desktop/src/main/services/ipc/runtimeBridge.ts
  • apps/desktop/src/main/services/jobs/jobEngine.test.ts
  • apps/desktop/src/main/services/localRuntime/localRuntimeConnectionPool.test.ts
  • apps/desktop/src/main/services/localRuntime/localRuntimeConnectionPool.ts
  • apps/desktop/src/main/services/pty/ptyService.test.ts
  • apps/desktop/src/main/services/pty/ptyService.ts
  • apps/desktop/src/main/services/updates/autoUpdateService.ts
  • apps/desktop/src/preload/global.d.ts
  • apps/desktop/src/preload/preload.test.ts
  • apps/desktop/src/preload/preload.ts
  • apps/desktop/src/renderer/browserMock.ts
  • apps/desktop/src/renderer/components/app/App.tsx
  • apps/desktop/src/renderer/components/app/App.workKeepAlive.test.tsx
  • apps/desktop/src/renderer/components/app/AppShell.tsx
  • apps/desktop/src/renderer/components/app/SettingsPage.tsx
  • apps/desktop/src/renderer/components/app/TabNav.test.tsx
  • apps/desktop/src/renderer/components/app/TopBar.test.tsx
  • apps/desktop/src/renderer/components/app/TopBar.tsx
  • apps/desktop/src/renderer/components/automations/ActionRow.tsx
  • apps/desktop/src/renderer/components/automations/AutomationsPage.tsx
  • apps/desktop/src/renderer/components/automations/AutomationsTemplatesPage.tsx
  • apps/desktop/src/renderer/components/automations/RulesTab.tsx
  • apps/desktop/src/renderer/components/automations/components/RuleEditorPanel.tsx
  • apps/desktop/src/renderer/components/chat/AgentChatComposer.tsx
  • apps/desktop/src/renderer/components/chat/AgentChatMessageList.test.tsx
  • apps/desktop/src/renderer/components/chat/AgentChatMessageList.tsx
  • apps/desktop/src/renderer/components/chat/AgentChatPane.tsx
  • apps/desktop/src/renderer/components/chat/ChatSubagentsPanel.test.tsx
  • apps/desktop/src/renderer/components/chat/ChatSubagentsPanel.tsx
  • apps/desktop/src/renderer/components/chat/chatExecutionSummary.ts
  • apps/desktop/src/renderer/components/chat/codex/CodexImageGenerationCard.test.tsx
  • apps/desktop/src/renderer/components/cto/CtoPage.tsx
  • apps/desktop/src/renderer/components/cto/ctoUi.test.tsx
  • apps/desktop/src/renderer/components/files/FilesPage.tsx
  • apps/desktop/src/renderer/components/graph/WorkspaceGraphPage.tsx
  • apps/desktop/src/renderer/components/history/HistoryPage.tsx
  • apps/desktop/src/renderer/components/history/useTimelineStore.ts
  • apps/desktop/src/renderer/components/lanes/LanesPage.tsx
  • apps/desktop/src/renderer/components/lanes/useLaneWorkSessions.ts
  • apps/desktop/src/renderer/components/missions/InterventionPanel.tsx
  • apps/desktop/src/renderer/components/missions/MissionActiveContext.tsx
  • apps/desktop/src/renderer/components/missions/MissionChatV2.tsx
  • apps/desktop/src/renderer/components/missions/MissionHeader.tsx
  • apps/desktop/src/renderer/components/missions/MissionLogsTab.tsx
  • apps/desktop/src/renderer/components/missions/MissionTabContainer.test.tsx
  • apps/desktop/src/renderer/components/missions/MissionTabContainer.tsx
  • apps/desktop/src/renderer/components/missions/MissionThreadMessageList.test.ts
  • apps/desktop/src/renderer/components/missions/MissionsPage.tsx
  • apps/desktop/src/renderer/components/missions/ModelSelector.tsx
  • apps/desktop/src/renderer/components/missions/OrchestratorActivityFeed.tsx
  • apps/desktop/src/renderer/components/missions/useMissionRunView.ts
  • apps/desktop/src/renderer/components/missions/useMissionsStore.ts
  • apps/desktop/src/renderer/components/prs/PRsPage.tsx
  • apps/desktop/src/renderer/components/prs/shared/PrMarkdown.tsx
  • apps/desktop/src/renderer/components/prs/state/PrsContext.tsx
  • apps/desktop/src/renderer/components/review/ReviewPage.tsx
  • apps/desktop/src/renderer/components/terminals/TerminalView.test.tsx
  • apps/desktop/src/renderer/components/terminals/TerminalView.tsx
  • apps/desktop/src/renderer/components/terminals/cliLaunch.test.ts
  • apps/desktop/src/renderer/components/terminals/useWorkSessions.test.ts
  • apps/desktop/src/renderer/components/terminals/useWorkSessions.ts
  • apps/desktop/src/renderer/lib/sessionListCache.ts
  • apps/desktop/src/renderer/state/appStore.test.ts
  • apps/desktop/src/renderer/state/appStore.ts
  • apps/desktop/src/shared/chatSubagents.ts
  • apps/desktop/src/shared/cliLaunch.ts
  • apps/desktop/src/shared/ipc.ts
  • apps/desktop/src/shared/types/automations.ts
  • apps/desktop/src/shared/types/chat.ts
  • apps/desktop/src/shared/types/config.ts
  • apps/desktop/src/shared/types/sessions.ts
  • apps/desktop/src/test/setup.ts
  • apps/ios/ADE/Services/SyncService.swift
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ade/automations-fixes-619117dc

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.

@capy-ai
Copy link
Copy Markdown

capy-ai Bot commented May 19, 2026

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.

Comment on lines +45 to +48
// Vertical offset of the first selectable roster row in the rendered chat-info
// pane (header + status + plan + goal occupy the preceding lines). Used only by
// the mouse-click → row mapper.
const SUBAGENT_PANE_TABLE_START_LINE = 4;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 SUBAGENT_PANE_TABLE_START_LINE is defined but never referenced in this file and is not exported. The comment references a mouse-click row mapper that does not exist here. Either export the constant for the TUI consumer or remove it.

Suggested change
// Vertical offset of the first selectable roster row in the rendered chat-info
// pane (header + status + plan + goal occupy the preceding lines). Used only by
// the mouse-click → row mapper.
const SUBAGENT_PANE_TABLE_START_LINE = 4;
// Vertical offset of the first selectable roster row in the rendered chat-info
// pane (header + status + plan + goal occupy the preceding lines). Used only by
// the mouse-click → row mapper.
export const SUBAGENT_PANE_TABLE_START_LINE = 4;
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src/shared/chatSubagents.ts
Line: 45-48

Comment:
`SUBAGENT_PANE_TABLE_START_LINE` is defined but never referenced in this file and is not exported. The comment references a mouse-click row mapper that does not exist here. Either export the constant for the TUI consumer or remove it.

```suggestion
// Vertical offset of the first selectable roster row in the rendered chat-info
// pane (header + status + plan + goal occupy the preceding lines). Used only by
// the mouse-click → row mapper.
export const SUBAGENT_PANE_TABLE_START_LINE = 4;
```

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

Fix in Claude Code

Comment on lines 12929 to +12932
runtime.webSearchActionsByItemId.clear();
runtime.itemTurnIdByItemId.clear();
runtime.agentMessageScopeByTurn.clear();
runtime.codexAgentIndexByTurn.delete(turnId);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Turn-level Codex agent-index maps cleared globally on interruption

runtime.codexAgentIndexByTurn.delete(turnId) correctly removes only the finished turn at normal completion, but the interrupted-turn handler calls runtime.codexAgentIndexByTurn.clear(), removing every turn's index map at once. If parallel Codex collab agents span multiple concurrent turns, an interrupt in one turn erases counter state for all others — subsequent agents restart numbering from #1 and may produce duplicate Agent #N labels.

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src/main/services/chat/agentChatService.ts
Line: 12929-12932

Comment:
**Turn-level Codex agent-index maps cleared globally on interruption**

`runtime.codexAgentIndexByTurn.delete(turnId)` correctly removes only the finished turn at normal completion, but the interrupted-turn handler calls `runtime.codexAgentIndexByTurn.clear()`, removing every turn's index map at once. If parallel Codex collab agents span multiple concurrent turns, an interrupt in one turn erases counter state for all others — subsequent agents restart numbering from `#1` and may produce duplicate `Agent #N` labels.

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

Fix in Claude Code

@arul28 arul28 merged commit 4f38c5e into main May 19, 2026
28 checks passed
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