orca/docs/reference/react-performance-audit.md

346 lines
102 KiB
Markdown

# React Performance Audit
Status: in progress
Started: 2026-05-29
Base commit: `b7fe967780` (`origin/main`, release v1.4.35)
## Goal
Scan the full React surface for `$perf` and `$react-useeffect` issues, keep coverage evidence here, and land the fixes as many small PRs with explicit merge-risk notes.
This document is the audit ledger. A section is not considered fully scanned until it has:
1. File inventory checked from the current worktree.
2. `useEffect` / `useLayoutEffect` / `useInsertionEffect` sites classified.
3. Perf-sensitive patterns checked: timers, subscriptions, observers, `JSON.stringify`, storage writes, polling, broad store subscriptions, large list rendering, and render-time derived state.
4. Each suspicious site dispositioned as "no change", "needs PR", or "covered by PR".
5. Merge risk recorded for every PR candidate.
## Scope
React hook call scan uses all repo `*.ts` and `*.tsx` files, then narrows to actual AST hook calls. The React Effect surface found on 2026-05-29 is:
- `src/renderer/src/**`
- `mobile/app/**`
- `mobile/src/**`
- `mobile/packages/expo-two-way-audio/src/hooks.ts`
Comment-only mentions outside those paths were ignored.
Initial inventory:
| Metric | Count |
| --------------------------------------------------- | ----: |
| Repo `*.ts` / `*.tsx` files | 3,011 |
| Files with real Effect hook calls | 285 |
| Effect hook call sites | 970 |
| `useLayoutEffect` / `useInsertionEffect` call sites | 44 |
| Empty dependency arrays | 111 |
| Effects with cleanup returns | 472 |
| Effects with subscription/listener/observer shape | 170 |
| Effects with timer or animation-frame shape | 128 |
| Effects with `JSON.stringify` shape | 2 |
| Set-state-shaped Effects needing manual review | 270 |
| `useMemo` call sites in React scope | 633 |
| `useCallback` call sites in React scope | 1,415 |
| `useSyncExternalStore` call sites in React scope | 8 |
## Coverage Ledger
Current count after low-risk PRs #3038, #3041, #3042, #3044, #3051, #3052, #3053, #3054, #3055, #3056, #3058, #3059, #3060, #3062, #3063, #3064, #3065, #3066, #3067, #3068, #3069, #3083, #3087, #3091, #3100, #3104, #3122, #3160, #3164, #3166, #3223, #3244, #3271, #3273, #3294, #3296, #3298, and #3300: 910 Effect hook call sites.
Open medium-risk PRs #3070, #3073, #3077, #3089, #3093, #3102, #3108, #3110, #3112, #3118, #3124, #3126, #3128, #3130, #3132, #3134, #3142, #3144, #3146, #3148, #3150, #3152, #3154, #3170, #3176, #3184, #3186, #3188, #3192, #3195, #3198, #3200, #3202, #3206, #3218, #3220, #3226, #3228, #3234, #3240, #3242, #3247, #3257, #3269, #3275, #3277, #3283, #3289, #3292, and #3303 each project to 909 Effect hook call sites on the current merged baseline; open medium-risk PRs #3097, #3106, #3116, #3120, #3136, #3138, #3180, #3210, #3214, #3238, #3255, #3261, #3281, #3285, and #3287 each project to 908; open medium-risk PRs #3114, #3168, and #3259 each project to 907; open medium-risk PRs #3095, #3140, and #3230 each project to 906; open medium-risk PR #3079 projects to 900; open high-risk PRs #3157, #3212, and #3253 each project to 909; open high-risk PR #3267 projects to 908; open high-risk PR #3075 projects to 906; open high-risk PR #3250 projects to 905; and open high-risk PR #3081 projects to 902. These are not counted in the merged baseline until reviewed and merged.
| Area | Files / signal | Scan status | Notes |
| ------------------------------ | -------------------------------------------------------------------------------------------------------- | --------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| Renderer app shell | `src/renderer/src/App.tsx`, root components | Inventory complete, manual review in progress | Confirmation dialog active request mirror covered by #3091; onboarding settings detour reset covered by #3122; quick workspace agent selection repair covered by #3148; Cmd+J selection repair covered by #3164; smart workspace command highlight covered by #3192; App lazy-modal mount bookkeeping covered by #3220; shared reduced-motion media-query hook covered by #3287. Continue checking global listeners, beforeunload, media-query, and active-tab repair. |
| Terminal / PTY | `components/Terminal.tsx`, `components/terminal-pane/**`, `components/terminal/**` | Inventory complete, manual review pending | Mobile driver overlay collapse repair covered by #3170; floating workspace first-open bounds normalization covered by #3269; unused legacy terminal shell/shortcut/hook files deleted by #3271. High-risk area: xterm lifecycle, scrollback, remote/mobile parity, focus, WebGL, resize. |
| Renderer mobile page | `components/mobile/**` | Inventory complete, manual review in progress | Mobile pairing page stage repair covered by #3180. Continue checking QR generation, mobile-page IPC, and paired-device polling. |
| Browser pane | `components/browser-pane/**` | Inventory complete, manual review in progress | Highest Effect density: 62 sites in `BrowserPane.tsx`. Browser ref mirrors covered by #3081; BrowserFind debounced-query state covered by #3275. Continue with driver sync, address bar derived state, remaining find state, webview lifetime. |
| Editor / markdown / Monaco | `components/editor/**` | Inventory complete, manual review in progress | Untitled rename reset covered by #3083; copy feedback timers covered by #3097; combined diff local state repairs covered by #3120; combined diff note-copy timer covered by #3218; DiffViewer first-diff auto-scroll reset covered by #3257; editor path-copy timer covered by #3277; PDF find open/reset Effect covered by #3289; editor tab rename focus covered by #3303. Check editor model cleanup, preview scroll restore, search debounce, generated decorations. |
| Sidebar / worktrees | `components/sidebar/**` | Inventory complete, manual review in progress | Orca hook trust checkbox reset covered by #3089; delete dialog one-shot checkbox reset covered by #3134; Add Repo clone destination auto-fill covered by #3150; sidebar live-width mirror covered by #3160; worktree selection pruning covered by #3166; SSH reconnect prompts covered by #3267; nested repo indeterminate checkbox covered by #3294; workspace title rename focus covered by #3296; workspace title editing notification covered by #3298; worktree metadata notes resize covered by #3300. Continue with drag/drop global listeners and kanban pointer flows. |
| Workspace cleanup | `components/workspace-cleanup/**` | Inventory complete, manual review in progress | Active cleanup-view repair covered by #3195. Continue checking destructive removal, repo filtering, scan refresh, and SSH/disconnected blockers. |
| Right sidebar / source control | `components/right-sidebar/**` | Inventory complete, manual review in progress | Source-control selection ref mirrors covered by #3075; Create PR dialog submit reset covered by #3184; commit-failure dialog identity repair covered by #3202; diff-comments clear confirmation repair covered by #3206; diff-notes copy feedback timers covered by #3210; selection stale-key pruning covered by #3212. Continue checking polling, PR checks, file explorer watch/reveal, and source-control local resets. Git provider compatibility required. |
| Settings | `components/settings/**` | Inventory complete, manual review in progress | Repository hook local editor visibility covered by #3093; lazy section mounted-state bookkeeping covered by #3128; browser home/Kagi draft sync covered by #3136; general auto-save/Open In draft sync covered by #3138; Source Control AI instruction drafts covered by #3140; notification volume draft sync covered by #3142; repo Source Control AI override draft sync covered by #3144; Quick Commands add intent covered by #3146; Mobile QR polling count capture covered by #3152; integration preflight status derivation covered by #3154; SSH reset-relay dialog cleanup covered by #3157; diagnostics bundle cleanup ref mirror covered by #3176. Continue with draft mirrors while keeping SSH and cross-platform settings behavior intact. |
| Automations | `components/automations/**` | Inventory complete, manual review in progress | Combobox open-focus Effects covered by #3100; run-history selection repair covered by #3104; external run-table selection repair covered by #3102; detail-page selection resets covered by #3106; create-from branch search reset covered by #3132. Continue with draft defaulting, polling, and completion detection. |
| Issue, PR, task pages | `TaskPage.tsx`, `PullRequestPage.tsx`, `GitHubItemDialog.tsx`, `GitLabItemDialog.tsx`, Linear components | Inventory complete, manual review in progress | Linear estimate input sync covered by #3108; Linear sub-issue list sync covered by #3110; GitHub project date draft sync covered by #3112; GitHub reviewer-picker active index covered by #3114; GitHub project column state covered by #3116; GitHub Project visible-table cache covered by #3186; GitHub Project dialog state covered by #3214; GitLab comment draft reset covered by #3124; Linear title/description draft sync covered by #3130; GitHub assignee dirty-flag reset covered by #3255; GitHub reviewer-request local sync covered by #3259; GitHub link-copy feedback timers covered by #3285; GitLab task filter repair covered by #3292. Continue large-file scan with separate GitHub, GitLab, Linear, and generic review behavior. |
| Onboarding / feature wall | `components/onboarding/**`, `components/feature-wall/**` | Inventory complete, manual review in progress | Select portal root Effects covered by #3087; tour visited-marker Effects covered by #3095; persisted completion close reset covered by #3188; onboarding settings hydration covered by #3198; unused orchestration notifications page deleted by #3273; feature-wall skill installed-state notification Effects covered by #3281; session-depth open publish Effects covered by #3283; shared reduced-motion media-query hook covered by #3287. Continue with demo timers and telemetry while avoiding telemetry semantic changes. |
| Status, dashboard, activity | `components/status-bar/**`, `components/dashboard/**`, `components/activity/**`, `components/pet/**` | Inventory complete, manual review in progress | Status-bar account menu close reset covered by #3051; pet overlay size clamp covered by #3118; Activity selected-thread repair covered by #3126; Workspace Space row-state repairs covered by #3168; Resource Manager Space scan-ready latch covered by #3200; pet reduced-motion subscription covered by #3287. Check interval sharing, retained agent state, activity terminal portals. |
| Mobile app routes | `mobile/app/**` | Inventory complete, manual review in progress | Pair-confirm route-code parsing covered by #3240; host home new-worktree route action covered by #3242; Accounts unused client ref covered by #3244; mobile home shared-client ref mirror covered by #3247; session route terminal/tab ref mirrors covered by #3250; tasks route client ref mirror covered by #3253; tasks route workspace agent selection covered by #3261. Continue with large `tasks.tsx` state/polling Effects, session route cleanup Effects, home route ref mirrors, and remote-client parity. |
| Mobile shared source | `mobile/src/**` | Inventory complete, manual review in progress | TextInputModal and CustomKeyModal open-state resets covered by #3223; BottomDrawer mount bookkeeping covered by #3226; MobileBrowserPane address sync covered by #3228; MobileBrowserPane ref mirrors covered by #3230; useMobileDictation ref mirrors covered by #3234; NewWorktreeModal agent selection covered by #3238. Continue with transport client context plus NewWorktreeModal open/reset, SSH, agent-detection, and setup-hook fetch Effects. |
| Expo two-way audio hook | `mobile/packages/expo-two-way-audio/src/hooks.ts` | Inventory complete, manual review pending | Single Effect plus `useSyncExternalStore`; verify native subscription cleanup. |
| Tests with hook mocks | `*.test.ts`, `*.test.tsx`, e2e comments | Inventory complete, manual review pending | Do not count comment-only mentions as app Effect sites; update tests beside behavior changes. |
## Current Findings Queue
These are candidate batches, not final conclusions. Each item needs code inspection before implementation.
| Candidate PR | Area | Symptom / wasted work to prove | Likely files | Merge risk |
| ------------ | ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | -------------- |
| PR A | Small controlled-input resets | Extra render pass from Effects that mirror one prop into local draft state. | `BrowserAddressBar.tsx` covered by #3038; `BrowserFind.tsx` covered by #3275; continue with `PdfFind.tsx`, selected settings draft fields | Low to medium |
| PR B | Settings draft hydration | Multiple independent Effects mirror persisted settings into draft state. | `components/settings/**` | Medium |
| PR C | Browser pane Effect cluster | Large Effect cluster may mix external webview sync, derived UI state, and event-specific state repair. | `BrowserPane.tsx`, `useGrabMode.ts`, browser tabs | High |
| PR D | Terminal tab repair and lifecycle | Effects repair active terminal/browser tab state after render; could cause extra render and focus churn. | `Terminal.tsx`, `TerminalPane.tsx` | High |
| PR E | Right-sidebar polling and source-control state repair | PR checks, branch snapshots, file explorer watch/reveal may repeat work after unrelated state changes. | `ChecksPanel.tsx`, `SourceControl.tsx`, `useGitStatusPolling.ts`, file explorer hooks | High |
| PR F | Mobile route monoliths | Mobile task/session routes have many chained Effects and timer/refetch patterns. | `mobile/app/h/[hostId]/tasks.tsx`, `mobile/app/h/[hostId]/session/[worktreeId].tsx` | High |
| PR G | Mobile shared components | Visible/open Effects reset modal/drawer state and browser address state. | `mobile/src/components/**`, `mobile/src/browser/MobileBrowserPane.tsx` | Medium |
| PR H | Editor search/preview/decorations | Debounce and scroll-restore Effects may be legitimate external sync but need cleanup/count review. | `components/editor/**` | Medium to high |
| PR I | Feature wall/onboarding demos | Animation/demo Effects can often move to event handlers or tighter custom hooks. | `components/feature-wall/**`, `components/onboarding/**` | Low to medium |
| PR J | GitHub filter controls | Extra render pass from mirroring parsed reviewer qualifier into local mode state. | `PRFilterDropdowns.tsx` covered by #3041 | Low |
| PR K | Sidebar project filter | Extra render pass from mirroring the first filtered repo into command selection state. | `SidebarFilter.tsx` covered by #3042 | Low |
| PR L | Diff note edit draft | Extra render pass from mirroring saved note body into edit draft while not editing. | `DiffCommentCard.tsx` covered by #3044 | Low |
| PR M | Status-bar account menus | Extra render pass from closing Claude/Codex account submenus in Effects after the provider menu closes. | `StatusBar.tsx` covered by #3051 | Low |
| PR N | Browser tab favicon fallback | Extra render pass from resetting failed favicon state in an Effect after tab favicon identity changes. | `BrowserTab.tsx` covered by #3052 | Low |
| PR O | Workspace title rename draft | Redundant draft sync Effect runs while the inline title rename input is not mounted. | `WorktreeTitleInlineRename.tsx` covered by #3053 | Low |
| PR P | Feature-wall tour static substep repair | Three no-op Effects scan static step arrays and repair ids that are only written from those arrays. | `FeatureWallTourSurface.tsx` covered by #3054 | Low |
| PR Q | Repo combobox mount-open state | Mount-only auto-open path uses an Effect and ref guard instead of initializing state from the prop. | `RepoCombobox.tsx` covered by #3055 | Low |
| PR R | Quick Open query reset | Extra render pass from clearing the Quick Open input after the dialog opens. | `QuickOpen.tsx` covered by #3056 | Low |
| PR S | Project group dialog open resets | Extra render pass from seeding name/delete dialog local state after the dialog opens. | `ProjectGroupNameDialog.tsx`, `ProjectGroupDeleteDialog.tsx` covered by #3058 | Low |
| PR T | Onboarding agent fallback disclosure | Extra render pass from opening the fallback agent list when a selected agent first appears there. | `AgentStep.tsx` covered by #3059 | Low |
| PR U | Feature-wall tour workflow resets | Four local reset Effects run after workflow changes or close instead of in the selection/close path. | `FeatureWallTourSurface.tsx` covered by #3060 | Low |
| PR V | Workspace board selection pruning | Local kanban selection is repaired in an Effect after the drawer closes or board rows change. | `use-workspace-kanban-selection.ts` covered by #3062 | Low |
| PR W | Workspace board column resize | Two mirror Effects sync the latest commit callback and external committed width after render. | `use-workspace-kanban-column-resize.ts` covered by #3063 | Low |
| PR X | Terminal quick-command dialog draft | Dialog draft and agent preset search are reset in an Effect after the dialog opens or retargets. | `TerminalQuickCommandDialog.tsx` covered by #3064 | Low |
| PR Y | Onboarding notification settings ref | A ref mirror Effect keeps notification handlers pointed at the latest settings. | `NotificationStep.tsx` covered by #3065 | Low |
| PR Z | Onboarding agent-selection ref mirrors | Five ref mirror Effects keep stable onboarding handlers pointed at latest selection/detection snapshots. | `use-onboarding-flow.ts` covered by #3066 | Low |
| PR AA | Workspace board drag ref mirrors | Area-selection and card-drag pointer handlers receive latest board callbacks through Effect-updated refs. | `use-workspace-kanban-area-selection.ts`, `use-workspace-kanban-card-pointer-drag.ts` covered by #3067 | Low |
| PR AB | Feature-wall tour telemetry refs | Close telemetry reads source/depth payload inputs through Effect-updated refs. | `use-feature-wall-tour-telemetry.ts` covered by #3068 | Low |
| PR AC | Onboarding persisted theme ref | The theme cleanup ref mirrors the latest persisted setting through an Effect. | `use-onboarding-flow.ts` covered by #3069 | Low |
| PR AD | Terminal window blur restart snapshot | A mount-only Effect rewrites the same startup blur snapshot already captured by the lazy ref initializer. | `TerminalWindowSection.tsx` covered by #3070 | Medium |
| PR AE | New-workspace composer note ref | A note ref mirror Effect runs after each note edit so stable PR/MR selection callbacks can read latest text. | `useComposerState.ts` covered by #3073 | Medium |
| PR AF | Source-control selection ref mirrors | Four ref mirror Effects keep stable source-control row handlers pointed at latest selection inputs. | `useSourceControlSelection.ts` covered by #3075 | High |
| PR AG | Notebook cell editor callback refs | A ref mirror Effect keeps embedded Monaco save/deactivate handlers pointed at latest callbacks. | `IpynbViewer.tsx` covered by #3077 | Medium |
| PR AH | Rich markdown editor ref mirrors | Nine ref mirror Effects keep stable ProseMirror/menu handlers pointed at latest editor UI state. | `RichMarkdownEditor.tsx` covered by #3079 | Medium |
| PR AI | Browser pane ref mirrors | Eight ref mirror Effects keep browser/webview callbacks and latest tab state available to stable handlers. | `BrowserPane.tsx`, `useGrabMode.ts` covered by #3081 | High |
| PR AJ | Untitled markdown rename draft reset | Save-as dialog draft fields reset in an Effect after open instead of before the first open paint. | `UntitledFileRenameDialog.tsx` covered by #3083 | Low |
| PR AK | Onboarding/feature-wall select portal roots | Two mount Effects query the active overlay/dialog root only to keep select menus above fullscreen surfaces. | `NotificationStep.tsx`, `AiCommitPrSettingsCard.tsx` covered by #3087 | Low |
| PR AL | Orca hook trust dialog checkbox reset | The "always trust" checkbox resets after open, leaving one possible paint with the previous decision. | `OrcaYamlTrustDialog.tsx` covered by #3089 | Medium |
| PR AM | Confirmation dialog active request mirror | Active confirmation request was mirrored into local state/ref in an Effect, adding a render pass per request. | `confirmation-dialog.tsx` covered by #3091 | Low |
| PR AN | Repository hook local editor visibility | The local hook script editor was revealed by an Effect after persisted local script content arrived. | `RepositoryHooksSection.tsx` covered by #3093 | Medium |
| PR AO | Feature-wall tour visited markers | Four Effects marked visible workflows/substeps as visited after render instead of in the open/select/continue transitions. | `FeatureWallTourSurface.tsx` covered by #3095 | Medium |
| PR AP | Editor copy feedback timers | Copy success indicators started their auto-clear timers in Effects after render rather than in the copy handlers. | `EditorPanel.tsx`, `MarkdownPreview.tsx` covered by #3097 | Medium |
| PR AQ | Combobox open focus | Four comboboxes focused search inputs and seeded cmdk highlight state in Effects after opening. | `AgentCombobox.tsx`, `RepoCombobox.tsx`, `WorkspaceCombobox.tsx`, `CreateFromPicker.tsx` covered by #3100 | Low |
| PR AR | Automation run-table selection repair | External automation run selection was repaired in an Effect after the visible run page changed. | `ExternalAutomationRunTable.tsx` covered by #3102 | Medium |
| PR AS | Automation run-history selection repair | Run-history row selection was repaired in an Effect after the automation run list changed. | `AutomationRunHistory.tsx` covered by #3104 | Low |
| PR AT | Automation detail-page selection resets | Internal and external automation run detail pages were cleared in Effects after selected automation/external keys changed. | `AutomationsPage.tsx` covered by #3106 | Medium |
| PR AU | Linear estimate input sync | Linear custom estimate input was mirrored from the issue estimate in an Effect while the popover was closed. | `LinearItemDrawer.tsx` covered by #3108 | Medium |
| PR AV | Linear sub-issue list sync | Linear sub-issue rows were mirrored from the selected issue in an Effect so optimistic creates could append local rows. | `LinearIssueWorkspace.tsx` covered by #3110 | Medium |
| PR AW | GitHub project date draft sync | GitHub Project date cells mirrored the source field value into local input draft state in an Effect. | `ProjectCell.tsx` covered by #3112 | Medium |
| PR AX | GitHub reviewer picker active index | Three GitHub review request pickers reset active keyboard selection in Effects after query or row-count changes. | `PullRequestPage.tsx`, `GitHubItemDialog.tsx`, `TaskPage.tsx` covered by #3114 | Medium |
| PR AY | GitHub Project column state | Project view column visibility and width preferences were reloaded in Effects after project/view scope changes. | `ProjectViewList.tsx` covered by #3116 | Medium |
| PR AZ | Pet overlay size clamp | Pet overlay position was repaired in an Effect after the persisted overlay size changed. | `PetOverlay.tsx` covered by #3118 | Medium |
| PR BA | Combined diff local state repairs | File-tree highlight and clear-notes dialog state were repaired in Effects after diff entry or note-count changes. | `CombinedDiffViewer.tsx` covered by #3120 | Medium |
| PR BB | Onboarding settings detour reset | The App-root onboarding detour flag was cleared in an Effect after Settings navigation or onboarding eligibility changed. | `App.tsx` covered by #3122 | Low |
| PR BC | GitLab comment draft reset | The GitLab MR/issue comment draft was cleared in an Effect after the selected sheet item changed. | `GitLabItemDialog.tsx` covered by #3124 | Medium |
| PR BD | Activity selected-thread repair | Activity selected thread state was cleared in an Effect after retained agent/tab rows changed. | `ActivityPrototypePage.tsx` covered by #3126 | Medium |
| PR BE | Settings lazy-section mounted state | Settings remembered newly needed lazy sections in an Effect after search/navigation changed the visible set. | `Settings.tsx` covered by #3128 | Medium |
| PR BF | Linear title/description draft sync | Linear issue title and description drafts were synced from source issue data in an Effect after item or field updates. | `LinearIssueTextEditor.tsx` covered by #3130 | Medium |
| PR BG | Automations create-from branch search | Create-from branch search query/results were cleared in an Effect after the selected repo changed. | `CreateFromPicker.tsx` covered by #3132 | Medium |
| PR BH | Delete dialog one-shot confirmation | The delete-workspace "don't ask again" checkbox was reset in an Effect after the dialog closed. | `DeleteWorktreeDialog.tsx` covered by #3134 | Medium |
| PR BI | Browser settings text drafts | Browser home-page and Kagi session-link drafts were synced from persisted settings in Effects after source changes. | `BrowserPane.tsx`, `KagiSessionLinkForm.tsx` covered by #3136 | Medium |
| PR BJ | General settings drafts | Auto-save delay and Open In launcher drafts were synced from persisted settings in Effects after source changes. | `GeneralPane.tsx` covered by #3138 | Medium |
| PR BK | Source Control AI instruction drafts | Commit-message, pull-request, and branch-name instruction drafts plus parent discard reset were synchronized in Effects. | `CommitMessageAiPane.tsx` covered by #3140 | Medium |
| PR BL | Notification volume draft | Notification custom-sound volume draft and latest-settings ref were synchronized in an Effect after settings changes. | `NotificationsPane.tsx` covered by #3142 | Medium |
| PR BM | Repo Source Control AI override draft | Repo-specific Source Control AI override draft was synchronized from persisted repo settings in an Effect after source changes. | `RepositorySourceControlAiSection.tsx` covered by #3144 | Medium |
| PR BN | Quick Commands add intent | Quick Commands add-dialog deep-link intent opened from a settings signal in an Effect after the pane rendered. | `QuickCommandsPane.tsx` covered by #3146 | Medium |
| PR BO | Quick workspace agent selection | Quick-create agent override was repaired in an Effect after detection or disabled-agent settings invalidated it. | `NewWorkspaceComposerModal.tsx`, `quick-workspace-agent-selection.ts` covered by #3148 | Medium |
| PR BP | Add Repo clone destination default | Clone destination was auto-filled in an Effect after entering the local clone step or after settings hydration. | `AddRepoDialog.tsx`, `clone-defaults.ts` covered by #3150 | Medium |
| PR BQ | Mobile QR pairing poll count | The paired-device count used to start QR polling was captured in an Effect after the QR data URL rendered. | `MobilePane.tsx` covered by #3152 | Medium |
| PR BR | Integrations preflight status mirrors | Source-host integration statuses and account labels were mirrored from preflight store state in an Effect after Settings rendered. | `IntegrationsPane.tsx`, `integrations-pane-status.ts` covered by #3154 | Medium |
| PR BS | SSH reset-relay dialog cleanup | Pending reset-relay confirmation was cleared in an Effect after the selected target began connecting or reconnecting. | `SshTargetDestructiveActions.tsx`, `ssh-target-action-state.ts` covered by #3157 | High |
| PR BT | Sidebar live-width mirror | Sidebar root mirrored the committed width into the live drag CSS variable in a second passive Effect. | `components/sidebar/index.tsx` covered by #3160 | Low |
| PR BU | Cmd+J selected-row repair | The jump palette repaired selected row state in an Effect after query or result-list changes. | `WorktreeJumpPalette.tsx`, `worktree-palette-create-action.test.ts` covered by #3164 | Low |
| PR BV | Sidebar selected-worktree pruning | The sidebar pruned selected worktree ids in an Effect after filters or grouping hid selected rows. | `WorktreeList.tsx` covered by #3166 | Low |
| PR BW | Workspace Space row-state repairs | The space manager repaired inspected row, selected ids, and treemap zoom in Effects after scan rows changed. | `WorkspaceSpaceManagerPanel.tsx`, `workspace-space-presentation.ts` covered by #3168 | Medium |
| PR BX | Mobile driver overlay collapse reset | The terminal mobile-driver overlay re-expanded from collapsed chip mode in an Effect after driver changes. | `MobileDriverOverlay.tsx`, `mobile-driver-overlay-collapse.ts` covered by #3170 | Medium |
| PR BY | Diagnostics bundle cleanup ref | The retained diagnostics bundle id was mirrored into a cleanup ref by a passive Effect after bundle creation. | `PrivacyDiagnosticsSection.tsx` covered by #3176 | Medium |
| PR BZ | Mobile pairing page stage repairs | Mobile page polling flipped from QR flow to paired summary, then reset the paired-view polling baseline, in two follow-up Effects. | `MobilePage.tsx`, `mobile-page-stage.ts` covered by #3180 | Medium |
| PR CA | Create PR submit close reset | The hosted review creation dialog reset submit/error state in an Effect after closing. | `CreatePullRequestDialog.tsx`, `ChecksPanel.tsx` covered by #3184 | Medium |
| PR CB | GitHub Project visible-table cache | The last filtered GitHub Project table was cached in state by an Effect after slug-index filtering completed. | `ProjectViewWrapper.tsx`, `project-visible-table-cache.ts` covered by #3186 | Medium |
| PR CC | Feature-wall persisted completion close reset | Persisted feature-wall completion sets were reread from localStorage in an Effect after the modal closed. | `use-persisted-feature-wall-completion.ts` covered by #3188 | Medium |
| PR CD | Smart workspace command highlight | The smart new-workspace picker repaired cmdk command highlight in an Effect after rows, query freshness, or source intent changed. | `SmartWorkspaceNameField.tsx`, `smart-workspace-command-value.ts` covered by #3192 | Medium |
| PR CE | Workspace cleanup active view | The cleanup dialog repaired the active nav section in an Effect after scan/filter counts made the requested section empty. | `WorkspaceCleanupDialog.tsx`, `workspace-cleanup-view-selection.ts` covered by #3195 | Medium |
| PR CF | Onboarding settings hydration | The onboarding wizard re-synced saved theme/default-agent settings in an Effect after async settings hydration. | `use-onboarding-flow.ts`, `onboarding-settings-hydration.ts` covered by #3198 | Medium |
| PR CG | Resource Manager Space scan-ready latch | The status-bar Resource Manager ready dot was repaired in an Effect after Space scan completion, popover open, or Space page navigation. | `ResourceUsageStatusSegment.tsx`, `resource-usage-space-scan-ready.ts` covered by #3200 | Medium |
| PR CH | Commit failure dialog identity | The Source Control commit failure details dialog reset stale open state in an Effect after the active failure identity changed. | `SourceControl.tsx`, `commit-failure-dialog-state.ts` covered by #3202 | Medium |
| PR CI | Diff comments clear confirmation | The Source Control note-clear confirmation closed stale pending state in an Effect after active worktree or note counts changed. | `SourceControl.tsx`, `diff-comments-clear-dialog-state.ts` covered by #3206 | Medium |
| PR CJ | Diff notes copy feedback timers | The Source Control note copy success indicators started auto-dismiss timers in Effects after copy handlers set copied state. | `SourceControl.tsx` covered by #3210 | Medium |
| PR CK | Source Control selected-key pruning | Bulk selection keys and range anchors were pruned in an Effect after visible Source Control rows changed. | `useSourceControlSelection.ts` covered by #3212 | High |
| PR CL | GitHub Project dialog state | Project repo-backed and slug fallback dialogs were closed in Effects after repo membership or slug-index readiness changed. | `ProjectViewWrapper.tsx`, `project-dialog-state.ts` covered by #3214 | Medium |
| PR CM | Combined diff note-copy timer | The combined diff note-copy success indicator started its auto-dismiss timer in an Effect after the copy handler set copied state. | `CombinedDiffViewer.tsx` covered by #3218 | Medium |
| PR CN | App lazy-modal mount state | Root lazy modal ids were retained in an Effect after `activeModal` changed, adding a render pass before first-use modal mount. | `App.tsx`, `lazy-modal-mount-state.ts` covered by #3220 | Medium |
| PR CO | Mobile shared modal open resets | Mobile TextInput and custom-key modals reset local drafts in Effects after opening, leaving one possible stale first paint. | `TextInputModal.tsx`, `CustomKeyModal.tsx` covered by #3223 | Low |
| PR CP | Mobile BottomDrawer mounted state | The shared mobile drawer mounted after opening in a passive Effect, adding a null commit before drawer animations could start. | `BottomDrawer.tsx`, `bottom-drawer-mount-state.ts` covered by #3226 | Medium |
| PR CQ | Mobile browser address sync | The mobile browser address field synced tab URL changes in an Effect after focus/tab updates, leaving one stale paint after blur or tab URL changes. | `MobileBrowserPane.tsx`, `mobile-browser-address-sync.ts` covered by #3228 | Medium |
| PR CR | Mobile browser ref mirrors | Mobile browser gesture and stream handlers received frame metadata, layout, dialog, and zoom state through passive ref-mirror Effects. | `MobileBrowserPane.tsx` covered by #3230 | Medium |
| PR CS | Mobile dictation ref mirrors | Native audio/RPC dictation handlers received client, enabled, transcript, and error callbacks through a passive ref-mirror Effect. | `use-mobile-dictation.ts` covered by #3234 | Medium |
| PR CT | Mobile new-worktree agent selection | The create-workspace modal repaired preferred and unavailable selected-agent state in passive Effects after settings or agent detection changed. | `NewWorktreeModal.tsx`, `new-worktree-agent-selection.ts` covered by #3238 | Medium |
| PR CU | Mobile pair-confirm route parsing | The deep-link pair-confirm screen rendered once without an offer/error, then parsed the route pairing code and repaired status in a passive Effect. | `pair-confirm.tsx`, `pair-confirm-state.ts` covered by #3240 | Medium |
| PR CV | Mobile host new-worktree route action | Host home opened the create-workspace modal from `action=newWorktree` in a passive Effect after the route rendered. | host route index, `host-route-action-state.ts` covered by #3242 | Medium |
| PR CW | Mobile Accounts unused client ref | The Accounts route mirrored `client` into a ref in a passive Effect, but no code read that ref. | `mobile/app/h/[hostId]/accounts.tsx` covered by #3244 | Low |
| PR CX | Mobile home shared-client ref mirror | The home route copied shared host clients into a focus-callback ref in a passive Effect, delaying focus refreshes by one commit. | `mobile/app/index.tsx` covered by #3247 | Medium |
| PR CY | Mobile session terminal/tab ref mirrors | The mobile session route copied active tab, tab list, markdown doc, client, and connection snapshots into imperative refs in passive Effects after terminal input/session callbacks could already run. | `mobile/app/h/[hostId]/session/[worktreeId].tsx` covered by #3250 | High |
| PR CZ | Mobile tasks client ref mirror | The mobile Tasks route copied the shared client into a stale-request guard ref in a passive Effect, delaying guard freshness for async task loads. | `mobile/app/h/[hostId]/tasks.tsx` covered by #3253 | High |
| PR DA | GitHub assignee dirty-flag reset | GitHub issue/PR edit sections reset the optimistic assignee-edit guard in a passive Effect after an item switch, so the assignee sync Effect could skip the new item for one commit. | `GitHubItemDialog.tsx`, `PullRequestPage.tsx` covered by #3255 | Medium |
| PR DB | DiffViewer first-diff auto-scroll reset | DiffViewer reset its one-shot first-diff scroll flag in a layout Effect after `modelKey` changed. | `DiffViewer.tsx` covered by #3257 | Medium |
| PR DC | GitHub reviewer-request local sync | GitHub reviewer request pickers mirrored incoming `reviewRequests` into optimistic local state in passive Effects after item switches/refetches. | `GitHubItemDialog.tsx`, `PullRequestPage.tsx`, `TaskPage.tsx` covered by #3259 | Medium |
| PR DD | Mobile Tasks workspace agent selection | The workspace-create drawer repaired automatic and unavailable agent choices in passive Effects after settings or SSH/local detection changed. | `mobile/app/h/[hostId]/tasks.tsx`, `workspace-agent-selection.ts` covered by #3261 | Medium |
| PR DE | Sidebar SSH reconnect prompts | Active sidebar worktree and nested lineage-child reconnect prompts opened from passive Effects after disconnected SSH state rendered. | `WorktreeCard.tsx`, `WorktreeList.tsx` covered by #3267 | High |
| PR DF | Floating workspace first-open bounds | Floating workspace panel normalized first-open bounds in a passive Effect after the initial hidden/open commit. | `FloatingTerminalPanel.tsx` covered by #3269 | Medium |
| PR DG | Unused terminal shell hooks | Four React Effect call sites lived only in unused terminal shell/shortcut/hook files. | `TerminalShell.tsx`, `useTerminalShortcuts.ts`, `useTerminalTabs.ts` covered by #3271 | Low |
| PR DH | Unused feature-wall notifications page | Two React Effect call sites lived only in an unused feature-wall orchestration page. | `NotificationsPage.tsx` covered by #3273 | Low |
| PR DI | Browser find debounce state | The webview find bar stored a debounced copy of query state through a second passive Effect before searching. | `BrowserFind.tsx` covered by #3275 | Medium |
| PR DJ | Editor path-copy feedback timer | The editor header path-copy toast started its auto-dismiss timer in a passive Effect after the copy handler set copied state. | `EditorPanel.tsx` covered by #3277 | Medium |
| PR DK | Feature-wall skill installed state | Orchestration and browser-use setup cards notified the tour parent of installed state from passive Effects after render. | `FeatureWallTourSurface.tsx`, `FeatureWallBody.tsx`, `FeatureWallTourPanel.tsx`, `OrchestrationSetupCard.tsx`, `BrowserUseSkillSetupCard.tsx`, `useInstalledAgentSkills.ts` covered by #3281 | Medium |
| PR DL | Feature-wall session-depth publishing | Session-depth reset and summary-publish Effects both published the same tour-depth summary on the modal open edge. | `use-feature-wall-session-depth.ts` covered by #3283 | Medium |
| PR DM | GitHub link-copy feedback timers | GitHub issue/PR link-copy buttons started their auto-dismiss timers from copied-state Effects after the copy handler set local feedback state. | `GitHubItemDialog.tsx`, `PullRequestPage.tsx` covered by #3285 | Medium |
| PR DN | Shared reduced-motion media query hook | UpdateCard, PetOverlay, and feature-wall/onboarding helpers each owned separate media-query subscription Effects for the same reduced-motion preference. | `usePrefersReducedMotion.ts`, `UpdateCard.tsx`, `PetOverlay.tsx`, `feature-wall-modal-helpers.ts` covered by #3287 | Medium |
| PR DO | PDF find open/reset state | PDF find focused the input and closed/reset match counters from a passive open-state Effect after the find bar rendered or hid. | `PdfFind.tsx`, `PdfViewer.tsx` covered by #3289 | Medium |
| PR DP | GitLab task filter repair | Switching between GitLab MR and issue views repaired invalid stale chip filters in a passive Effect after render. | `TaskPage.tsx` covered by #3292 | Medium |
| PR DQ | Nested repo select-all indeterminate state | The nested repo select-all checkbox set its visual indeterminate state in a passive Effect after selection changes. | `NestedRepoTreePreview.tsx` covered by #3294 | Low |
| PR DR | Workspace title rename focus | Inline workspace title rename focused and selected its input from a passive Effect after edit mode rendered. | `WorktreeTitleInlineRename.tsx` covered by #3296 | Low |
| PR DS | Workspace title editing notification | Inline workspace title rename notified parent cards that editing mode changed from a passive Effect after the rename input rendered. | `WorktreeTitleInlineRename.tsx` covered by #3298 | Low |
| PR DT | Worktree metadata notes resize | The worktree metadata notes textarea resized itself from a passive Effect after the comment draft rendered. | `WorktreeMetaDialog.tsx` covered by #3300 | Low |
| PR DU | Editor tab rename focus | Editor file-tab rename focused and selected the filename input from a passive Effect after rename mode rendered. | `EditorFileTab.tsx` covered by #3303 | Medium |
## Merge Risk Scale
| Risk | Criteria | Required verification |
| ------ | --------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| Low | Isolated local UI state, no persistence, no IPC, no terminal/browser/source-control behavior. | Targeted unit test if available plus `pnpm run typecheck:web`. |
| Medium | Settings, editor UI, mobile local UI, or state persisted per workspace but no transport protocol changes. | Targeted tests plus manual interaction or focused Playwright/Electron check when UI behavior changes. |
| High | Terminal/PTY, browser webview, source control, mobile remote-client, SSH, polling, persistence, or provider behavior. | Targeted tests, `pnpm run typecheck:web`, and Electron or mobile/manual parity evidence as appropriate. |
## PR Log
| PR | Branch | Area | Risk | Status | Evidence |
| ----- | ------------------------------------ | ----------------------------------------------------------------------------- | ---- | ------ | ------------------------------------------------------------------------------------------------------------ |
| #3038 | `nwparker/react-perf` | Audit ledger plus browser address bar top-suggestion mirror Effect removal | Low | Merged | `pnpm exec oxlint src/renderer/src/components/browser-pane/BrowserAddressBar.tsx`; `pnpm run typecheck:web`. |
| #3041 | `nwparker/react-perf-pr-filter` | PR reviewer filter mode derived from parsed query plus explicit user override | Low | Merged | `pnpm exec oxlint src/renderer/src/components/github/PRFilterDropdowns.tsx`; `pnpm run typecheck:web`. |
| #3042 | `nwparker/react-perf-sidebar-filter` | Sidebar project filter command selection derived from filtered repos | Low | Merged | `pnpm exec oxlint src/renderer/src/components/sidebar/SidebarFilter.tsx`; `pnpm run typecheck:web`. |
| #3044 | `nwparker/react-perf-low-risk-2` | Diff note card removes saved-body-to-draft mirror Effect | Low | Merged | `pnpm exec oxlint src/renderer/src/components/diff-comments/DiffCommentCard.tsx`; `pnpm run typecheck:web`. |
| #3051 | `nwparker/react-perf-low-risk-3` | Status-bar account submenus collapse in provider menu open-change handlers | Low | Merged | `pnpm exec oxlint src/renderer/src/components/status-bar/StatusBar.tsx`; `pnpm run typecheck:web`. |
| #3052 | `nwparker/react-perf-low-risk-4` | Browser tab favicon failure reset happens during render for new favicon IDs | Low | Merged | `pnpm exec oxlint src/renderer/src/components/tab-bar/BrowserTab.tsx`; `pnpm run typecheck:web`. |
| #3053 | `nwparker/react-perf-low-risk-5` | Inline workspace-title rename removes inactive draft sync Effect | Low | Merged | `pnpm exec oxlint src/renderer/src/components/sidebar/WorktreeTitleInlineRename.tsx`; `pnpm run typecheck:web`. |
| #3054 | `nwparker/react-perf-low-risk-6` | Feature-wall tour removes static substep id repair Effects | Low | Merged | `pnpm exec oxlint src/renderer/src/components/feature-wall/FeatureWallTourSurface.tsx`; `pnpm run typecheck:web`. |
| #3055 | `nwparker/react-perf-low-risk-7` | Repo combobox initializes mount-open state without an Effect | Low | Merged | `pnpm exec oxlint src/renderer/src/components/repo/RepoCombobox.tsx`; `pnpm run typecheck:web`. |
| #3056 | `nwparker/react-perf-low-risk-8` | Quick Open clears its query on the open edge without a reset Effect | Low | Merged | `pnpm exec oxlint src/renderer/src/components/QuickOpen.tsx`; `pnpm run typecheck:web`. |
| #3058 | `nwparker/react-perf-project-group-dialogs` | Project group dialogs reset local open-state during render | Low | Merged | `pnpm exec oxlint src/renderer/src/components/sidebar/ProjectGroupDeleteDialog.tsx src/renderer/src/components/sidebar/ProjectGroupNameDialog.tsx`; `pnpm run typecheck:web`. |
| #3059 | `nwparker/react-perf-agent-step-latch` | Onboarding agent fallback disclosure latch updates during render | Low | Merged | `pnpm exec oxlint src/renderer/src/components/onboarding/AgentStep.tsx`; `pnpm run typecheck:web`. |
| #3060 | `nwparker/react-perf-feature-tour-resets` | Feature-wall tour reset state moves into workflow/close transitions | Low | Merged | `pnpm exec oxlint src/renderer/src/components/feature-wall/FeatureWallTourSurface.tsx`; `pnpm run typecheck:web`. |
| #3062 | `nwparker/react-perf-kanban-selection` | Workspace board selection pruning moves out of an Effect | Low | Merged | `pnpm exec oxlint src/renderer/src/components/sidebar/use-workspace-kanban-selection.ts`; `pnpm run typecheck:web`. |
| #3063 | `nwparker/react-perf-kanban-column` | Workspace board column width mirror Effects move to render-time synchronization | Low | Merged | `pnpm exec oxlint src/renderer/src/components/sidebar/use-workspace-kanban-column-resize.ts`; `pnpm run typecheck:web`. |
| #3064 | `nwparker/react-perf-quick-command-dialog` | Terminal quick-command dialog resets draft state during render | Low | Merged | `pnpm exec oxlint src/renderer/src/components/terminal-quick-commands/TerminalQuickCommandDialog.tsx`; `pnpm run typecheck:web`. |
| #3065 | `nwparker/react-perf-notification-step-ref` | Onboarding notification settings ref mirror moves out of an Effect | Low | Merged | `pnpm exec oxlint src/renderer/src/components/onboarding/NotificationStep.tsx`; `pnpm run typecheck:web`. |
| #3066 | `nwparker/react-perf-onboarding-agent-refs` | Onboarding agent-selection ref mirrors move out of Effects | Low | Merged | `pnpm exec oxlint src/renderer/src/components/onboarding/use-onboarding-flow.ts`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/onboarding/agent-picked-payload.test.ts`; `pnpm run typecheck:web`. |
| #3067 | `nwparker/react-perf-kanban-drag-refs` | Workspace board drag ref mirrors move out of Effects | Low | Merged | `pnpm exec oxlint src/renderer/src/components/sidebar/use-workspace-kanban-area-selection.ts src/renderer/src/components/sidebar/use-workspace-kanban-card-pointer-drag.ts`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/sidebar/use-workspace-kanban-card-pointer-drag.test.ts src/renderer/src/components/sidebar/workspace-kanban-area-selection.test.ts`; `pnpm run typecheck:web`. |
| #3068 | `nwparker/react-perf-feature-wall-telemetry-ref` | Feature-wall tour telemetry ref mirror moves out of an Effect | Low | Merged | `pnpm exec oxlint src/renderer/src/components/feature-wall/use-feature-wall-tour-telemetry.ts`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/feature-wall/use-feature-wall-tour-telemetry.test.ts`; `pnpm run typecheck:web`. |
| #3069 | `nwparker/react-perf-onboarding-theme-ref` | Onboarding persisted theme ref mirror moves out of an Effect | Low | Merged | `pnpm exec oxlint src/renderer/src/components/onboarding/use-onboarding-flow.ts`; `pnpm run typecheck:web`. |
| #3070 | `nwparker/react-perf-terminal-window-ref` | Terminal window blur startup snapshot removes redundant mount Effect | Medium | Open | `pnpm exec oxlint src/renderer/src/components/settings/TerminalWindowSection.tsx`; `pnpm run typecheck:web`. |
| #3073 | `nwparker/react-perf-composer-note-ref` | New-workspace composer note ref mirror moves out of an Effect | Medium | Open | `pnpm exec oxlint src/renderer/src/hooks/useComposerState.ts`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/hooks/composer-branch-selection.test.ts`; `pnpm run typecheck:web`. |
| #3075 | `nwparker/react-perf-source-control-selection-refs` | Source-control selection ref mirrors move out of Effects | High | Open | `pnpm exec oxlint src/renderer/src/components/right-sidebar/useSourceControlSelection.ts`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/right-sidebar/useSourceControlSelection.test.ts`; `pnpm run typecheck:web`. |
| #3077 | `nwparker/react-perf-ipynb-cell-editor-refs` | Notebook cell editor callback refs move out of an Effect | Medium | Open | `pnpm exec oxlint src/renderer/src/components/editor/IpynbViewer.tsx`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/editor/ipynb-parse.test.ts`; `pnpm run typecheck:web`. |
| #3079 | `nwparker/react-perf-rich-markdown-refs` | Rich markdown editor ref mirrors move out of Effects | Medium | Open | `pnpm exec oxlint src/renderer/src/components/editor/RichMarkdownEditor.tsx`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/editor/rich-markdown-key-handler.test.ts src/renderer/src/components/editor/RichMarkdownSlashMenu.test.tsx src/renderer/src/components/editor/markdown-doc-completions.test.ts src/renderer/src/components/editor/rich-markdown-commands.test.ts`; `pnpm run typecheck:web`. |
| #3081 | `nwparker/react-perf-browser-ref-mirrors` | Browser pane ref mirrors move out of Effects | High | Open | `pnpm exec oxlint src/renderer/src/components/browser-pane/useGrabMode.ts src/renderer/src/components/browser-pane/BrowserPane.tsx`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/browser-pane/browser-pane-page-selection.test.ts src/renderer/src/components/browser-pane/context-menu-positioning.test.ts`; `pnpm run typecheck:web`; Electron sanity launch/attach on CDP port 9333, branch identity confirmed, zero console errors, existing browser webview target observed. |
| #3083 | `nwparker/react-perf-untitled-rename-dialog` | Untitled markdown rename dialog draft reset moves out of an Effect | Low | Merged | `pnpm exec oxlint src/renderer/src/components/editor/UntitledFileRenameDialog.tsx`; `pnpm run typecheck:web`. |
| #3087 | `nwparker/react-perf-tour-select-portals` | Onboarding/feature-wall select portal roots move out of Effects | Low | Merged | `pnpm exec oxlint src/renderer/src/components/feature-wall/AiCommitPrSettingsCard.tsx src/renderer/src/components/onboarding/NotificationStep.tsx`; `pnpm run typecheck:web`. |
| #3089 | `nwparker/react-perf-orca-yaml-trust-reset` | Orca hook trust checkbox reset moves out of an Effect | Medium | Open | `pnpm exec oxlint src/renderer/src/components/sidebar/OrcaYamlTrustDialog.tsx`; `pnpm run typecheck:web`. |
| #3091 | `nwparker/react-perf-confirmation-dialog` | Confirmation dialog active request mirror moves out of an Effect | Low | Merged | `pnpm exec oxlint src/renderer/src/components/confirmation-dialog.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 933 -> 932. |
| #3093 | `nwparker/react-perf-repo-hooks-local-editor` | Repository hook local editor visibility is derived from user-open state and non-empty local script content | Medium | Open | `pnpm exec oxlint src/renderer/src/components/settings/RepositoryHooksSection.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 932 -> 931. |
| #3095 | `nwparker/react-perf-feature-wall-visited-events` | Feature-wall tour visited markers move from Effects to open/select/continue handlers | Medium | Open | `pnpm exec oxlint src/renderer/src/components/feature-wall/FeatureWallTourSurface.tsx`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/feature-wall/use-feature-wall-completion.test.ts src/renderer/src/components/feature-wall/use-feature-wall-tour-telemetry.test.ts`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 932 -> 928. |
| #3097 | `nwparker/react-perf-editor-copy-timers` | Editor copy feedback clear timers move into the copy handlers | Medium | Open | `pnpm exec oxlint src/renderer/src/components/editor/MarkdownPreview.tsx src/renderer/src/components/editor/EditorPanel.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 932 -> 930. |
| #3100 | `nwparker/react-perf-combobox-open-focus` | Combobox open focus and cmdk highlight seeding move out of Effects | Low | Merged | `pnpm exec oxlint src/renderer/src/components/agent/AgentCombobox.tsx src/renderer/src/components/repo/RepoCombobox.tsx src/renderer/src/components/automations/WorkspaceCombobox.tsx src/renderer/src/components/automations/CreateFromPicker.tsx`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/agent/AgentCombobox.test.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 932 -> 928. |
| #3102 | `nwparker/react-perf-automation-run-selection` | External automation run-table selection repair moves into page navigation/render derivation | Medium | Open | `pnpm exec oxlint src/renderer/src/components/automations/ExternalAutomationRunTable.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 928 -> 927. |
| #3104 | `nwparker/react-perf-automation-history-selection` | Automation run-history row selection is derived during render | Low | Merged | `pnpm exec oxlint src/renderer/src/components/automations/AutomationRunHistory.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 928 -> 927. |
| #3106 | `nwparker/react-perf-automation-page-resets` | Automation detail-page resets move into automation/external selection handlers | Medium | Open | `pnpm exec oxlint src/renderer/src/components/automations/AutomationsPage.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 927 -> 925. |
| #3108 | `nwparker/react-perf-linear-estimate-input` | Linear estimate input sync moves to popover open | Medium | Open | `pnpm exec oxlint src/renderer/src/components/LinearItemDrawer.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 927 -> 926. |
| #3110 | `nwparker/react-perf-linear-subissues` | Linear sub-issue rows derive from issue data plus optimistic additions | Medium | Open | `pnpm exec oxlint src/renderer/src/components/LinearIssueWorkspace.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 927 -> 926. |
| #3112 | `nwparker/react-perf-project-date-draft` | GitHub project date-cell draft sync moves to render-time source reconciliation | Medium | Open | `pnpm exec oxlint src/renderer/src/components/github-project/ProjectCell.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 927 -> 926. |
| #3114 | `nwparker/react-perf-reviewer-index` | GitHub reviewer picker active index resets during render | Medium | Open | `pnpm exec oxlint src/renderer/src/components/PullRequestPage.tsx src/renderer/src/components/GitHubItemDialog.tsx src/renderer/src/components/TaskPage.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 927 -> 924. |
| #3116 | `nwparker/react-perf-project-view-columns` | GitHub Project column hidden/width state reloads during render on scope changes | Medium | Open | `pnpm exec oxlint src/renderer/src/components/github-project/ProjectViewList.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 927 -> 925. |
| #3118 | `nwparker/react-perf-pet-size-clamp` | Pet overlay position clamps during render on size changes | Medium | Open | `pnpm exec oxlint src/renderer/src/components/pet/PetOverlay.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 927 -> 926. |
| #3120 | `nwparker/react-perf-combined-diff-state` | Combined diff file-tree highlight and clear-notes dialog repair during render | Medium | Open | `pnpm exec oxlint src/renderer/src/components/editor/CombinedDiffViewer.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 927 -> 925. |
| #3122 | `nwparker/react-perf-onboarding-detour` | App onboarding settings detour reset moves out of an Effect | Low | Merged | `pnpm exec oxlint src/renderer/src/App.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 927 -> 926. |
| #3124 | `nwparker/react-perf-gitlab-comment-draft` | GitLab comment draft reset moves out of an Effect | Medium | Open | `pnpm exec oxlint src/renderer/src/components/GitLabItemDialog.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 926 -> 925. |
| #3126 | `nwparker/react-perf-activity-selection` | Activity selected-thread repair moves out of an Effect | Medium | Open | `pnpm exec oxlint src/renderer/src/components/activity/ActivityPrototypePage.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 926 -> 925. |
| #3128 | `nwparker/react-perf-settings-mounted-sections` | Settings lazy-section mounted bookkeeping moves out of an Effect | Medium | Open | `pnpm exec oxlint src/renderer/src/components/settings/Settings.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 926 -> 925. |
| #3130 | `nwparker/react-perf-linear-text-drafts` | Linear title/description draft sync moves out of an Effect | Medium | Open | `pnpm exec oxlint src/renderer/src/components/LinearIssueTextEditor.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 926 -> 925. |
| #3132 | `nwparker/react-perf-create-from-search` | Automations create-from branch search reset moves out of an Effect | Medium | Open | `pnpm exec oxlint src/renderer/src/components/automations/CreateFromPicker.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 926 -> 925. |
| #3134 | `nwparker/react-perf-delete-worktree-confirm` | Delete-workspace one-shot confirmation checkbox reset moves out of an Effect | Medium | Open | `pnpm exec oxlint src/renderer/src/components/sidebar/DeleteWorktreeDialog.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 926 -> 925. |
| #3136 | `nwparker/react-perf-browser-settings-drafts` | Browser home-page and Kagi session-link draft sync moves out of Effects | Medium | Open | `pnpm exec oxlint src/renderer/src/components/settings/BrowserPane.tsx src/renderer/src/components/settings/KagiSessionLinkForm.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 926 -> 924. |
| #3138 | `nwparker/react-perf-general-settings-drafts` | General auto-save delay and Open In launcher draft sync moves out of Effects | Medium | Open | `pnpm exec oxlint src/renderer/src/components/settings/GeneralPane.tsx`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/settings/GeneralPane.test.ts`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 926 -> 924. |
| #3140 | `nwparker/react-perf-commit-ai-drafts` | Source Control AI instruction draft sync and discard reset move out of Effects | Medium | Open | `pnpm exec oxlint src/renderer/src/components/settings/CommitMessageAiPane.tsx src/renderer/src/components/settings/CommitMessageAiPane.test.tsx`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/settings/CommitMessageAiPane.test.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 926 -> 921. |
| #3142 | `nwparker/react-perf-notification-volume-draft` | Notification volume draft sync moves out of an Effect | Medium | Open | `pnpm exec oxlint src/renderer/src/components/settings/NotificationsPane.tsx src/renderer/src/components/settings/NotificationsPane.test.tsx`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/settings/NotificationsPane.test.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 926 -> 925. |
| #3144 | `nwparker/react-perf-repo-source-control-ai-draft` | Repo Source Control AI override draft sync moves out of an Effect | Medium | Open | `pnpm exec oxlint src/renderer/src/components/settings/RepositorySourceControlAiSection.tsx src/renderer/src/components/settings/RepositorySourceControlAiSection.test.ts`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/settings/RepositorySourceControlAiSection.test.ts`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 926 -> 925. |
| #3146 | `nwparker/react-perf-quick-commands-intent` | Quick Commands add-intent signal consumption moves out of an Effect | Medium | Open | `pnpm exec oxlint src/renderer/src/components/settings/QuickCommandsPane.tsx src/renderer/src/components/settings/QuickCommandsPane.test.ts`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/settings/QuickCommandsPane.test.ts`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 926 -> 925. |
| #3148 | `nwparker/react-perf-quick-agent-selection` | Quick workspace agent override repair moves out of an Effect | Medium | Open | `pnpm exec oxlint src/renderer/src/components/NewWorkspaceComposerModal.tsx src/renderer/src/lib/quick-workspace-agent-selection.ts src/renderer/src/lib/quick-workspace-agent-selection.test.ts`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/lib/quick-workspace-agent-selection.test.ts`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 926 -> 925. |
| #3150 | `nwparker/react-perf-add-repo-clone-default` | Add Repo clone destination auto-fill moves out of an Effect | Medium | Open | `pnpm exec oxlint src/renderer/src/components/sidebar/AddRepoDialog.tsx src/renderer/src/components/sidebar/clone-defaults.ts src/renderer/src/components/sidebar/clone-defaults.test.ts`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/sidebar/clone-defaults.test.ts`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 926 -> 925. |
| #3152 | `nwparker/react-perf-mobile-qr-polling` | Mobile QR device-count capture moves out of an Effect | Medium | Open | `pnpm exec oxlint src/renderer/src/components/settings/MobilePane.tsx src/renderer/src/components/settings/mobile-pairing-device-polling.ts src/renderer/src/components/settings/mobile-pairing-device-polling.test.ts`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/settings/mobile-pairing-device-polling.test.ts`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 926 -> 925. |
| #3154 | `nwparker/react-perf-integrations-status` | Integrations preflight status mirrors move out of an Effect | Medium | Open | `pnpm exec oxlint src/renderer/src/components/settings/IntegrationsPane.tsx src/renderer/src/components/settings/integrations-pane-status.ts src/renderer/src/components/settings/integrations-pane-status.test.ts`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/settings/integrations-pane-status.test.ts`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 926 -> 925. |
| #3157 | `nwparker/react-perf-ssh-reset-dialog` | SSH reset-relay dialog cleanup moves out of an Effect | High | Open | `pnpm exec oxlint src/renderer/src/components/settings/SshTargetDestructiveActions.tsx src/renderer/src/components/settings/ssh-target-action-state.ts src/renderer/src/components/settings/ssh-target-action-state.test.ts`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/settings/ssh-target-action-state.test.ts`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 926 -> 925. |
| #3160 | `nwparker/react-perf-sidebar-live-width` | Redundant sidebar live-width mirror Effect removed | Low | Merged | `pnpm exec oxlint src/renderer/src/components/sidebar/index.tsx src/renderer/src/hooks/useSidebarResize.ts`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/hooks/useSidebarResize.test.ts`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 926 -> 925. |
| #3164 | `nwparker/react-perf-worktree-palette-selection` | Cmd+J selected-row repair moves out of an Effect | Low | Merged | `pnpm exec oxlint src/renderer/src/components/WorktreeJumpPalette.tsx src/renderer/src/lib/worktree-palette-create-action.ts src/renderer/src/lib/worktree-palette-create-action.test.ts`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/lib/worktree-palette-create-action.test.ts`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 925 -> 924. |
| #3166 | `nwparker/react-perf-sidebar-selection-prune` | Sidebar selected-worktree pruning moves out of an Effect | Low | Merged | `pnpm exec oxlint src/renderer/src/components/sidebar/WorktreeList.tsx src/renderer/src/components/sidebar/worktree-multi-selection.ts src/renderer/src/components/sidebar/worktree-multi-selection.test.ts`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/sidebar/worktree-multi-selection.test.ts`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 924 -> 923. |
| #3168 | `nwparker/react-perf-workspace-space-state` | Workspace Space row-state repairs move out of Effects | Medium | Open | `pnpm exec oxlint src/renderer/src/components/status-bar/WorkspaceSpaceManagerPanel.tsx src/renderer/src/components/status-bar/workspace-space-presentation.ts src/renderer/src/components/status-bar/workspace-space-presentation.test.ts`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/status-bar/workspace-space-presentation.test.ts`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 923 -> 920. |
| #3170 | `nwparker/react-perf-mobile-driver-overlay-collapse` | Mobile driver overlay collapse reset moves out of an Effect | Medium | Open | `pnpm exec oxlint src/renderer/src/components/terminal-pane/MobileDriverOverlay.tsx src/renderer/src/components/terminal-pane/mobile-driver-overlay-collapse.ts src/renderer/src/components/terminal-pane/mobile-driver-overlay-collapse.test.ts`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/terminal-pane/mobile-driver-overlay-collapse.test.ts src/renderer/src/components/terminal-pane/mobile-driver-overlay-focus.test.ts`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 923 -> 922. |
| #3176 | `nwparker/react-perf-diagnostics-bundle-ref` | Diagnostics bundle cleanup ref mirror moves out of an Effect | Medium | Open | `pnpm exec oxlint src/renderer/src/components/settings/PrivacyDiagnosticsSection.tsx`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/settings/PrivacyPane.test.ts`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 923 -> 922. |
| #3180 | `nwparker/react-perf-mobile-page-stage` | Mobile pairing page stage repairs move into the device refresh path | Medium | Open | `pnpm exec oxlint src/renderer/src/components/mobile/MobilePage.tsx src/renderer/src/components/mobile/mobile-page-stage.ts src/renderer/src/components/mobile/mobile-page-stage.test.ts`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/mobile/mobile-page-stage.test.ts src/renderer/src/components/settings/mobile-pairing-device-polling.test.ts`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 923 -> 921. |
| #3184 | `nwparker/react-perf-create-pr-submit-reset` | Create PR dialog submit reset moves out of an Effect | Medium | Open | `pnpm exec oxlint src/renderer/src/components/right-sidebar/CreatePullRequestDialog.tsx src/renderer/src/components/right-sidebar/ChecksPanel.tsx`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/right-sidebar/checks-panel-content.test.tsx src/renderer/src/components/right-sidebar/checks-panel-git-status-snapshot.test.ts`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 923 -> 922. |
| #3186 | `nwparker/react-perf-project-visible-table-cache` | GitHub Project visible-table cache moves out of an Effect | Medium | Open | `pnpm exec oxlint src/renderer/src/components/github-project/ProjectViewWrapper.tsx src/renderer/src/components/github-project/project-visible-table-cache.ts src/renderer/src/components/github-project/project-visible-table-cache.test.ts`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/github-project/project-visible-table-cache.test.ts src/renderer/src/components/github-project/project-row-filtering.test.ts`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 923 -> 922. |
| #3188 | `nwparker/react-perf-feature-wall-persisted-reset` | Feature-wall persisted close reset Effect removed | Medium | Open | `pnpm exec oxlint src/renderer/src/components/feature-wall/use-persisted-feature-wall-completion.ts src/renderer/src/components/feature-wall/use-feature-wall-completion.ts`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/feature-wall/use-feature-wall-completion.test.ts src/renderer/src/components/feature-wall/use-feature-wall-tour-telemetry.test.ts`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 923 -> 922. |
| #3192 | `nwparker/react-perf-smart-name-command-value` | Smart workspace command highlight resolves during render | Medium | Open | `pnpm exec oxlint src/renderer/src/components/new-workspace/SmartWorkspaceNameField.tsx src/renderer/src/components/new-workspace/smart-workspace-command-value.ts src/renderer/src/components/new-workspace/smart-workspace-command-value.test.ts`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/new-workspace/smart-workspace-command-value.test.ts`; `pnpm run typecheck:web`; `git diff --check origin/main...HEAD`; AST Effect count 923 -> 922. |
| #3195 | `nwparker/react-perf-workspace-cleanup-view` | Workspace cleanup active view resolves during render | Medium | Open | `pnpm exec oxlint src/renderer/src/components/workspace-cleanup/WorkspaceCleanupDialog.tsx src/renderer/src/components/workspace-cleanup/workspace-cleanup-view-selection.ts src/renderer/src/components/workspace-cleanup/workspace-cleanup-view-selection.test.ts`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/workspace-cleanup/workspace-cleanup-view-selection.test.ts`; `pnpm run typecheck:web`; `git diff --check origin/main...HEAD`; AST Effect count 923 -> 922. |
| #3198 | `nwparker/react-perf-onboarding-settings-hydration` | Onboarding settings hydration resolves before commit | Medium | Open | `pnpm exec oxlint src/renderer/src/components/onboarding/use-onboarding-flow.ts src/renderer/src/components/onboarding/onboarding-settings-hydration.ts src/renderer/src/components/onboarding/onboarding-settings-hydration.test.ts`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/onboarding/onboarding-settings-hydration.test.ts src/renderer/src/components/onboarding/agent-picked-payload.test.ts src/renderer/src/components/onboarding/ThemeStep.test.ts`; `pnpm run typecheck:web`; `git diff --check origin/main...HEAD`; AST Effect count 923 -> 922. |
| #3200 | `nwparker/react-perf-resource-space-ready` | Resource Manager Space scan-ready latch resolves before commit | Medium | Open | `pnpm exec oxlint src/renderer/src/components/status-bar/ResourceUsageStatusSegment.tsx src/renderer/src/components/status-bar/resource-usage-space-scan-ready.ts src/renderer/src/components/status-bar/resource-usage-space-scan-ready.test.ts`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/status-bar/resource-usage-space-scan-ready.test.ts`; `pnpm run typecheck:web`; `git diff --check origin/main...HEAD`; AST Effect count 923 -> 922. |
| #3202 | `nwparker/react-perf-commit-failure-dialog` | Source Control commit-failure dialog identity resolves before commit | Medium | Open | `pnpm exec oxlint src/renderer/src/components/right-sidebar/SourceControl.tsx src/renderer/src/components/right-sidebar/commit-failure-dialog-state.ts src/renderer/src/components/right-sidebar/commit-failure-dialog-state.test.ts`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/right-sidebar/commit-failure-dialog-state.test.ts src/renderer/src/components/right-sidebar/CommitArea.test.tsx src/renderer/src/components/right-sidebar/commit-failure-summary.test.ts`; `pnpm run typecheck:web`; `git diff --check origin/main...HEAD`; AST Effect count 923 -> 922. |
| #3206 | `nwparker/react-perf-diff-comments-clear` | Source Control diff-comments clear confirmation resolves before commit | Medium | Open | `pnpm exec oxlint src/renderer/src/components/right-sidebar/SourceControl.tsx src/renderer/src/components/right-sidebar/diff-comments-clear-dialog-state.ts src/renderer/src/components/right-sidebar/diff-comments-clear-dialog-state.test.ts`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/right-sidebar/diff-comments-clear-dialog-state.test.ts`; `pnpm run typecheck:web`; `git diff --check origin/main...HEAD`; AST Effect count 923 -> 922. |
| #3210 | `nwparker/react-perf-diff-comments-copy-timers` | Source Control diff-notes copy reset timers move into copy handlers | Medium | Open | `pnpm exec oxlint src/renderer/src/components/right-sidebar/SourceControl.tsx`; `pnpm run typecheck:web`; `git diff --check origin/main...HEAD`; AST Effect count 923 -> 921. |
| #3212 | `nwparker/react-perf-source-selection-reconcile` | Source Control stale selected-key pruning resolves before commit | High | Open | `pnpm exec oxlint src/renderer/src/components/right-sidebar/useSourceControlSelection.ts src/renderer/src/components/right-sidebar/useSourceControlSelection.test.ts`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/right-sidebar/useSourceControlSelection.test.ts`; `pnpm run typecheck:web`; `git diff --check origin/main...HEAD`; AST Effect count 923 -> 922. |
| #3214 | `nwparker/react-perf-project-dialog-state` | GitHub Project dialog state resolves before commit | Medium | Open | `pnpm exec oxlint src/renderer/src/components/github-project/ProjectViewWrapper.tsx src/renderer/src/components/github-project/project-dialog-state.ts src/renderer/src/components/github-project/project-dialog-state.test.ts`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/github-project/project-dialog-state.test.ts`; `pnpm run typecheck:web`; `git diff --check origin/main...HEAD`; AST Effect count 923 -> 921. |
| #3218 | `nwparker/react-perf-combined-diff-copy-timer` | Combined diff note-copy reset timer moves into the copy handler | Medium | Open | `pnpm exec oxlint src/renderer/src/components/editor/CombinedDiffViewer.tsx`; `pnpm run typecheck:web`; `git diff --check origin/main...HEAD`; AST Effect count 923 -> 922. |
| #3220 | `nwparker/react-perf-app-lazy-modals` | App lazy-modal mount state resolves before commit | Medium | Open | `pnpm exec oxlint src/renderer/src/App.tsx src/renderer/src/lazy-modal-mount-state.ts src/renderer/src/lazy-modal-mount-state.test.ts`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/lazy-modal-mount-state.test.ts`; `pnpm run typecheck:web`; `git diff --check origin/main...HEAD`; AST Effect count 923 -> 922. |
| #3223 | `nwparker/react-perf-mobile-modal-resets` | Mobile shared modal draft resets move out of Effects | Low | Merged | `pnpm exec oxlint mobile/src/components/TextInputModal.tsx mobile/src/components/CustomKeyModal.tsx`; `pnpm run typecheck:web`; `git diff --check origin/main...HEAD`; AST Effect count 923 -> 921. Mobile package-local typecheck blocked by missing Expo/mobile deps/config in this checkout. |
| #3226 | `nwparker/react-perf-bottom-drawer-mounted` | Mobile BottomDrawer mounted state resolves before commit | Medium | Open | `pnpm exec oxlint mobile/src/components/BottomDrawer.tsx mobile/src/components/bottom-drawer-mount-state.ts mobile/src/components/bottom-drawer-mount-state.test.ts`; `pnpm run typecheck:web`; `git diff --check origin/main...HEAD`; `pnpm exec tsx -e "import { strict as assert } from 'node:assert'; import { resolveBottomDrawerMounted } from './mobile/src/components/bottom-drawer-mount-state.ts'; assert.equal(resolveBottomDrawerMounted(true, false), true); assert.equal(resolveBottomDrawerMounted(true, true), true); assert.equal(resolveBottomDrawerMounted(false, true), true); assert.equal(resolveBottomDrawerMounted(false, false), false); console.log('bottom-drawer-mount-state ok')"`; AST Effect count 921 -> 920. Mobile Vitest blocked by missing `expo/tsconfig.base` in this checkout. |
| #3228 | `nwparker/react-perf-mobile-browser-address` | Mobile browser address sync resolves before commit | Medium | Open | `pnpm exec oxlint mobile/src/browser/MobileBrowserPane.tsx mobile/src/browser/mobile-browser-address-sync.ts mobile/src/browser/mobile-browser-address-sync.test.ts`; `pnpm run typecheck:web`; `git diff --check origin/main...HEAD`; `pnpm exec tsx -e "import { strict as assert } from 'node:assert'; import { resolveMobileBrowserAddressSync } from './mobile/src/browser/mobile-browser-address-sync.ts'; assert.deepEqual(resolveMobileBrowserAddressSync({ focused: false, url: 'https://old.example/' }, { focused: false, url: 'https://new.example/' }), { nextState: { focused: false, url: 'https://new.example/' }, shouldSyncValue: true }); assert.deepEqual(resolveMobileBrowserAddressSync({ focused: false, url: 'https://old.example/' }, { focused: true, url: 'https://new.example/' }), { nextState: { focused: true, url: 'https://new.example/' }, shouldSyncValue: false }); assert.deepEqual(resolveMobileBrowserAddressSync({ focused: true, url: 'https://new.example/' }, { focused: false, url: 'https://new.example/' }), { nextState: { focused: false, url: 'https://new.example/' }, shouldSyncValue: true }); const previous = { focused: false, url: 'https://new.example/' }; assert.deepEqual(resolveMobileBrowserAddressSync(previous, { focused: false, url: 'https://new.example/' }), { nextState: previous, shouldSyncValue: false }); console.log('mobile-browser-address-sync ok')"`; AST Effect count 921 -> 920. Mobile Vitest blocked by missing `expo/tsconfig.base` in this checkout. |
| #3230 | `nwparker/react-perf-mobile-browser-refs` | Mobile browser ref mirrors move out of Effects | Medium | Open | `pnpm exec oxlint mobile/src/browser/MobileBrowserPane.tsx`; `pnpm run typecheck:web`; `git diff --check origin/main...HEAD`; AST Effect count 921 -> 917. |
| #3234 | `nwparker/react-perf-mobile-dictation-refs` | Mobile dictation ref mirrors move out of Effects | Medium | Open | `pnpm exec oxlint mobile/src/hooks/use-mobile-dictation.ts`; `pnpm run typecheck:web`; `git diff --check origin/main...HEAD`; AST Effect count 921 -> 920. |
| #3238 | `nwparker/react-perf-new-worktree-agent` | Mobile new-worktree agent selection resolves before commit | Medium | Open | `pnpm exec oxlint mobile/src/components/NewWorktreeModal.tsx mobile/src/components/new-worktree-agent-selection.ts mobile/src/components/new-worktree-agent-selection.test.ts`; `pnpm run typecheck:web`; `git diff --check origin/main...HEAD`; direct `pnpm exec tsx -e` assertions for new-worktree agent selection; AST Effect count 921 -> 919. Mobile Vitest and package-local typecheck blocked by missing mobile deps/config in this checkout. |
| #3240 | `nwparker/react-perf-pair-confirm-route` | Mobile pair-confirm route state resolves before commit | Medium | Open | `pnpm exec oxlint mobile/app/pair-confirm.tsx mobile/src/transport/pair-confirm-state.ts mobile/src/transport/pair-confirm-state.test.ts`; `pnpm run typecheck:web`; `git diff --check origin/main...HEAD`; direct `pnpm exec tsx -e` assertions for pair-confirm route state; AST Effect count 921 -> 920. Mobile Vitest blocked by missing mobile deps/config in this checkout. |
| #3242 | `nwparker/react-perf-host-new-worktree-action` | Mobile host new-worktree route action resolves before commit | Medium | Open | `pnpm exec oxlint mobile/app/h/[hostId]/index.tsx mobile/src/host-route-action-state.ts mobile/src/host-route-action-state.test.ts`; `pnpm run typecheck:web`; `git diff --check origin/main...HEAD`; direct `pnpm exec tsx -e` assertions for host route action state; AST Effect count 921 -> 920. Mobile Vitest blocked by missing mobile deps/config in this checkout. |
| #3244 | `nwparker/react-perf-mobile-accounts-client-ref` | Mobile Accounts unused client ref mirror removed | Low | Merged | `pnpm exec oxlint mobile/app/h/[hostId]/accounts.tsx`; `pnpm run typecheck:web`; `git diff --check origin/main...HEAD`; `git diff --check`; AST Effect count 921 -> 920. |
| #3247 | `nwparker/react-perf-mobile-home-client-ref` | Mobile home shared-client ref mirror moves out of an Effect | Medium | Open | `pnpm exec oxlint mobile/app/index.tsx`; `pnpm run typecheck:web`; `git diff --check origin/main...HEAD`; `git diff --check`; AST Effect count 920 -> 919. |
| #3250 | `nwparker/react-perf-mobile-session-refs` | Mobile session terminal/tab ref mirrors move out of Effects | High | Open | `pnpm exec oxlint mobile/app/h/[hostId]/session/[worktreeId].tsx`; `pnpm run typecheck:web`; `git diff --check origin/main...HEAD`; `git diff --check`; AST Effect count 920 -> 915. Mobile Vitest blocked by missing `expo/tsconfig.base` in this checkout. |
| #3253 | `nwparker/react-perf-mobile-tasks-client-ref` | Mobile Tasks client ref mirror moves out of an Effect | High | Open | `pnpm exec oxlint mobile/app/h/[hostId]/tasks.tsx`; `pnpm run typecheck:web`; `git diff --check origin/main...HEAD`; `git diff --check`; AST Effect count 920 -> 919. |
| #3255 | `nwparker/react-perf-github-assignee-reset` | GitHub assignee edit guard resets before commit | Medium | Open | `pnpm exec oxlint src/renderer/src/components/GitHubItemDialog.tsx src/renderer/src/components/PullRequestPage.tsx`; `pnpm run typecheck:web`; `git diff --check origin/main...HEAD`; `git diff --check`; AST Effect count 920 -> 918. |
| #3257 | `nwparker/react-perf-diff-viewer-autoscroll-ref` | DiffViewer first-diff auto-scroll reset moves out of a layout Effect | Medium | Open | `pnpm exec oxlint src/renderer/src/components/editor/DiffViewer.tsx`; `pnpm run typecheck:web`; `git diff --check origin/main...HEAD`; `git diff --check`; AST Effect count 920 -> 919. |
| #3259 | `nwparker/react-perf-github-review-requests-sync` | GitHub reviewer request local-state sync moves out of Effects | Medium | Open | `pnpm exec oxlint src/renderer/src/components/GitHubItemDialog.tsx src/renderer/src/components/PullRequestPage.tsx src/renderer/src/components/TaskPage.tsx`; `pnpm run typecheck:web`; `git diff --check origin/main...HEAD`; `git diff --check`; AST Effect count 920 -> 917. |
| #3261 | `nwparker/react-perf-mobile-task-agent-selection` | Mobile Tasks workspace-create agent selection resolves before commit | Medium | Open | `pnpm exec oxlint mobile/app/h/[hostId]/tasks.tsx mobile/src/tasks/workspace-agent-selection.ts mobile/src/tasks/workspace-agent-selection.test.ts`; `pnpm run typecheck:web`; `git diff --check origin/main...HEAD`; `git diff --check`; direct `pnpm exec tsx -e` assertions for workspace-agent selection; AST Effect count 920 -> 918. Mobile Vitest blocked by missing `expo/tsconfig.base` in this checkout. |
| #3267 | `nwparker/react-perf-sidebar-ssh-reconnect-prompt` | Sidebar SSH reconnect prompts resolve before commit | High | Open | `pnpm exec oxlint src/renderer/src/components/sidebar/WorktreeCard.tsx src/renderer/src/components/sidebar/WorktreeList.tsx`; `pnpm run typecheck:web`; `git diff --check origin/main...HEAD`; `git diff --check`; AST Effect count 920 -> 918. |
| #3269 | `nwparker/react-perf-floating-terminal-bounds` | Floating workspace first-open bounds normalize before commit | Medium | Open | `pnpm exec oxlint src/renderer/src/components/floating-terminal/FloatingTerminalPanel.tsx`; `pnpm run typecheck:web`; `git diff --check origin/main...HEAD`; `git diff --check`; AST Effect count 920 -> 919. |
| #3271 | `nwparker/react-perf-dead-terminal-shell` | Unused terminal shell/shortcut/hook modules removed | Low | Merged | `pnpm exec oxlint src/renderer/src/components/terminal`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 920 -> 916. |
| #3273 | `nwparker/react-perf-dead-notifications-page` | Unused feature-wall orchestration notifications page removed | Low | Merged | `pnpm exec oxlint src/renderer/src/components/feature-wall/agents-orchestration src/renderer/src/components/feature-wall/AgentsOrchestrationVisual.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 916 -> 914. |
| #3275 | `nwparker/react-perf-browser-find-debounce` | BrowserFind folds debounced query state into the webview search Effect | Medium | Open | `pnpm exec oxlint src/renderer/src/components/browser-pane/BrowserFind.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 914 -> 913. |
| #3277 | `nwparker/react-perf-editor-copy-path-timer` | Editor path-copy toast timeout moves into the copy handler | Medium | Open | `pnpm exec oxfmt --write src/renderer/src/components/editor/EditorPanel.tsx`; `pnpm exec oxlint src/renderer/src/components/editor/EditorPanel.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 914 -> 913. |
| #3281 | `nwparker/react-perf-feature-wall-skill-state` | Feature-wall setup-card installed-state notifications move out of child Effects | Medium | Open | `pnpm exec oxfmt --write src/renderer/src/hooks/useInstalledAgentSkills.ts src/renderer/src/components/settings/OrchestrationSetupCard.tsx src/renderer/src/components/feature-wall/BrowserUseSkillSetupCard.tsx src/renderer/src/components/feature-wall/FeatureWallBody.tsx src/renderer/src/components/feature-wall/FeatureWallTourPanel.tsx src/renderer/src/components/feature-wall/FeatureWallTourSurface.tsx`; `pnpm exec oxlint src/renderer/src/hooks/useInstalledAgentSkills.ts src/renderer/src/components/settings/OrchestrationSetupCard.tsx src/renderer/src/components/feature-wall/BrowserUseSkillSetupCard.tsx src/renderer/src/components/feature-wall/FeatureWallBody.tsx src/renderer/src/components/feature-wall/FeatureWallTourPanel.tsx src/renderer/src/components/feature-wall/FeatureWallTourSurface.tsx`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/feature-wall/use-feature-wall-completion.test.ts`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 914 -> 912. |
| #3283 | `nwparker/react-perf-feature-wall-session-depth` | Feature-wall session-depth open reset and publish Effects collapse into one Effect | Medium | Open | `pnpm exec oxfmt --write src/renderer/src/components/feature-wall/use-feature-wall-session-depth.ts`; `pnpm exec oxlint src/renderer/src/components/feature-wall/use-feature-wall-session-depth.ts`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/feature-wall/use-feature-wall-completion.test.ts`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 914 -> 913. |
| #3285 | `nwparker/react-perf-github-link-copy-timer` | GitHub issue/PR link-copy feedback timers move into copy handlers | Medium | Open | `pnpm exec oxfmt --write src/renderer/src/components/GitHubItemDialog.tsx src/renderer/src/components/PullRequestPage.tsx`; `pnpm exec oxlint src/renderer/src/components/GitHubItemDialog.tsx src/renderer/src/components/PullRequestPage.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 914 -> 912. |
| #3287 | `nwparker/react-perf-shared-reduced-motion-hook` | Reduced-motion media-query subscription shared across renderer surfaces | Medium | Open | `pnpm exec oxfmt --write src/renderer/src/hooks/usePrefersReducedMotion.ts src/renderer/src/components/feature-wall/feature-wall-modal-helpers.ts src/renderer/src/components/UpdateCard.tsx src/renderer/src/components/pet/PetOverlay.tsx`; `pnpm exec oxlint src/renderer/src/hooks/usePrefersReducedMotion.ts src/renderer/src/components/feature-wall/feature-wall-modal-helpers.ts src/renderer/src/components/UpdateCard.tsx src/renderer/src/components/pet/PetOverlay.tsx`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/UpdateCard.test.ts src/renderer/src/components/pet/pet-overlay-visibility.test.ts`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 914 -> 912. |
| #3289 | `nwparker/react-perf-pdf-find-open-reset` | PDF find open-state focus/reset moves out of a passive Effect | Medium | Open | `pnpm exec oxfmt --write src/renderer/src/components/editor/PdfFind.tsx src/renderer/src/components/editor/PdfViewer.tsx`; `pnpm exec oxlint src/renderer/src/components/editor/PdfFind.tsx src/renderer/src/components/editor/PdfViewer.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 914 -> 913. |
| #3292 | `nwparker/react-perf-task-gitlab-filter` | GitLab task filter validity resolves before commit | Medium | Open | `pnpm exec oxfmt --write src/renderer/src/components/TaskPage.tsx`; `pnpm exec oxlint src/renderer/src/components/TaskPage.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 914 -> 913. |
| #3294 | `nwparker/react-perf-nested-repo-indeterminate` | Nested repo select-all indeterminate checkbox state moves to a callback ref | Low | Merged | `pnpm exec oxfmt --write src/renderer/src/components/repo/NestedRepoTreePreview.tsx`; `pnpm exec oxlint src/renderer/src/components/repo/NestedRepoTreePreview.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 914 -> 913. |
| #3296 | `nwparker/react-perf-worktree-title-focus-ref` | Workspace title rename input focus moves to callback ref | Low | Merged | `pnpm exec oxfmt --write src/renderer/src/components/sidebar/WorktreeTitleInlineRename.tsx`; `pnpm exec oxlint src/renderer/src/components/sidebar/WorktreeTitleInlineRename.tsx`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/sidebar/WorktreeTitleInlineRename.test.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 913 -> 912. |
| #3298 | `nwparker/react-perf-worktree-title-editing-change` | Workspace title rename editing notifications move to handlers | Low | Merged | `pnpm exec oxfmt --write src/renderer/src/components/sidebar/WorktreeTitleInlineRename.tsx`; `pnpm exec oxlint src/renderer/src/components/sidebar/WorktreeTitleInlineRename.tsx`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/sidebar/WorktreeTitleInlineRename.test.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 912 -> 911. |
| #3300 | `nwparker/react-perf-worktree-meta-textarea-resize` | Worktree metadata notes textarea resizes from ref and input handlers | Low | Merged | `pnpm exec oxfmt --write src/renderer/src/components/sidebar/WorktreeMetaDialog.tsx`; `pnpm exec oxlint src/renderer/src/components/sidebar/WorktreeMetaDialog.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 911 -> 910. |
| #3303 | `nwparker/react-perf-editor-tab-rename-focus-ref` | Editor file-tab rename input focus moves to callback ref | Medium | Open | `pnpm exec oxfmt --write src/renderer/src/components/tab-bar/EditorFileTab.tsx src/renderer/src/components/tab-bar/EditorFileTab.test.tsx`; `pnpm exec oxlint src/renderer/src/components/tab-bar/EditorFileTab.tsx src/renderer/src/components/tab-bar/EditorFileTab.test.tsx`; `pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/tab-bar/EditorFileTab.test.tsx`; `pnpm run typecheck:web`; `git diff --check`; AST Effect count 910 -> 909. |
## Reproduction Commands
Run from the worktree root.
```bash
rg --files -g '*.tsx' -g '*.ts' | wc -l
rg -l "\\b(useEffect|useLayoutEffect|React\\.useEffect|React\\.useLayoutEffect)\\b" -g '*.tsx' -g '*.ts' | sort
```
The exact Effect-site counts above came from a TypeScript AST scan so comment-only mentions are not counted.