Skip to content

Unified frontend: Git Dashboard, PR listing, sidebar redesign, and settings cleanup#765

Merged
backnotprop merged 8 commits into
feat/unified-settingsfrom
feat/unified-refined-ux
May 21, 2026
Merged

Unified frontend: Git Dashboard, PR listing, sidebar redesign, and settings cleanup#765
backnotprop merged 8 commits into
feat/unified-settingsfrom
feat/unified-refined-ux

Conversation

@backnotprop
Copy link
Copy Markdown
Owner

Summary

  • Git Dashboard — new slide-in view showing PRs across all registered projects, grouped by Open/Draft/Merged with metric cards, diff stats, review badges, and click-to-launch review sessions
  • PR listing on landing page — per-project PR tab with stacked PR grouping via branch chain detection, multi-select parallel session launch
  • Sidebar redesign — animated sprite mascot header, Instrument Sans brand font, version display, compact session rows with mode-grouped headers, hover-triggered peek sidebar when collapsed
  • Settings cleanup — proper header bar (no more toggle overlap), Code Review Display tab rewrite with grouped sections and inline controls, Theme tab spacing fix, version info + feedback link
  • InfrastructurePRDetailedListItem type, fetchPRDetailedList fetcher, daemon endpoints for PR listing with 30s cache, directory typeahead prefix filtering, worktree-aware project registration, right-click project removal with session/history cleanup, shared formatSessionLabel for clean display names

Test plan

  • Open frontend, add a project with a GitHub remote
  • Expand project — PRs tab shows open PRs, Worktrees tab shows worktrees as rows
  • Select multiple PRs/worktrees, click Code Review — parallel sessions launch
  • Click "Git Dashboard →" — slides to dashboard with grouped PRs across all projects
  • Click a PR row in dashboard — review session launches
  • Close sidebar, hover left edge — peek sidebar slides in with backdrop
  • Open Settings — verify no toggle/button overlap, compact display tab, version info
  • Right-click a project — context menu with "Remove project"

… management to frontend landing page

- Fix worktree project registration: session factory now uses addProject() instead of registerProject() so worktrees nest under parent projects
- Fix directory typeahead: handle partial paths by splitting into parent dir + prefix filter
- Add daemon endpoint GET /daemon/projects/prs for listing PRs via GitHub/GitLab CLI
- Add PR list with stacked PR detection using headBranch/baseBranch chain matching
- Add multi-select for PRs and worktrees with parallel session launch via Promise.allSettled
- Restructure worktrees from badge pills to row layout matching PR list style
- Add tabbed expansion panel (PRs default, Worktrees) under each project
- Add shared formatSessionLabel() for clean display names across sidebar, landing page, and toasts
- Add right-click context menu to remove projects with session cancellation and history cleanup
- Add PullRequestIcon with state-based coloring (open/merged/closed)
…y tab layout

- Replace absolute-positioned close button with dedicated header bar to prevent toggle overlap
- Remove settings cog icon, add version number and send feedback link
- Rewrite Code Review Display tab with grouped sections (Typography, Layout, Options)
- Replace font size slider with +/- stepper matching tab size pattern
- Make segmented controls inline with labels for compact layout
- Add live preview showing both font family and size together
- Fix Theme tab spacing: add divider and gap between Mode and Theme sections
- Move Line Backgrounds toggle to end of Options (sub-setting at bottom)
- Add PRDetailedListItem type and fetchPRDetailedList for dashboard-specific PR data
- Add daemon endpoint GET /daemon/projects/prs/detailed with 30s cache
- Add git-dashboard-store (Zustand) with parallel multi-project fetch and dedup
- Build Git Dashboard with PRRow, PRGroup, MetricCards components
- Dashboard groups PRs into Open/Draft/Recently Merged with scroll-to navigation
- Clicking a PR row launches a review session via createReviewSession
- Add CSS translateX slide transition between landing page and dashboard
- Clean up settings dialog: proper header bar, version info, send feedback link
- Rewrite Code Review Display tab with grouped sections and compact inline controls
- Fix Theme tab spacing between Mode and Theme sections
- Redesign sidebar: sprite mascot header, Instrument Sans brand font, version display
- Remove session status dots/checkmarks, move mode icons to group headers
- Compact sidebar session rows (text-xs, h-7) with alignment spacers
- Embed sidebar trigger in landing page card instead of dedicated nav bar
- Add right-click context menu for project removal with session/history cleanup
- Fix directory typeahead prefix filtering for partial path input
- Fix worktree project registration via addProject() instead of registerProject()
- Add multi-select session launch with parallel Promise.allSettled
- Add stacked PR grouping via headBranch/baseBranch chain detection
- Add shared formatSessionLabel() for clean display across sidebar/landing/toasts
- Deduplicate PRs across projects sharing the same remote
- Extract AppSidebarContent for reuse between real sidebar and peek
- SidebarPeek renders a floating panel on left-edge hover (80vh, centered)
- Backdrop overlay fades in at bg-black/30 behind the panel
- Panel slides in/out at 150ms, backdrop at 200ms
- Uses bg-sidebar token for consistent background with real sidebar
- Remove session tooltip hovers
- Only active when sidebar is collapsed
…surfacing

- Fix path traversal: sanitize project name before use in rmSync path
- Switch project deletion from name-based to cwd-based identification
- Deduplicate archive launches by cwd when multiple selections share a project
- Gate dashboard PR fetch on visibility (only fetch when dashboard slide is active)
- Gate worktree fetch on expanded state (don't shell out until user expands)
- Track project count in dashboard store for cache invalidation on add/remove
- Surface auth and CLI errors in dashboard instead of showing misleading empty state
- Consolidate duplicate PR ref resolution into single handler for both endpoints
- Delete unused carousel.tsx and remove motion dependency
- Move @radix-ui/react-context-menu from devDependencies to dependencies
…n remove, path guard

- Fix SidebarPeek timer leak: clear existing timeout before setting new one in hide()
- PR tabs now refetch after 30s instead of being permanently cached
- Dashboard isEmpty derived from visible groups, not raw array (fixes blank state for closed-only repos)
- Dashboard clears stale PRs when all projects are removed
- Defense-in-depth: verify resolved rmSync path is inside history root before deleting
- Fix handleRemove missing project.cwd in useCallback dependency array
@backnotprop backnotprop merged commit 8520673 into feat/unified-settings May 21, 2026
@backnotprop backnotprop deleted the feat/unified-refined-ux branch May 21, 2026 21:02
backnotprop added a commit that referenced this pull request May 22, 2026
…#766)

* Add shadcn Dialog and Tabs primitives to frontend

Dialog wraps @radix-ui/react-dialog with DiffKit prototype styling:
bg-black/55 backdrop, rounded-2xl card, entrance animation with
reduced-motion support. Sized at max-w-4xl for the settings dialog.

Tabs wraps @radix-ui/react-tabs with vertical orientation support.
Tab triggers use text-foreground by default (per design audit).

Also backlogged AddProjectDialog migration to use these primitives.

* Add unified settings dialog with vertical tabs layout

The frontend app now has a single app-level settings dialog accessible
via Cmd+, (Ctrl+, on Windows/Linux) or the sidebar Settings button.
It uses a wide Radix Dialog (896px) with vertical tabs grouped into
four sections: General, Plan Review, Code Review, and Integrations.

Tab content components are imported from the shared UI package:
- ThemeTab, KeyboardShortcuts, HooksTab (already separate files)
- GitTab, ReviewDisplayTab, CommentsTab (newly exported from Settings.tsx)
- SegmentedControl, ToggleSwitch (extracted to settings/shared.tsx)

The existing per-surface Settings modals remain for standalone mode.

* Wire per-surface gear icon to unified settings dialog when embedded

Both PlanAppEmbedded and ReviewAppEmbedded now accept an onOpenSettings
callback. When provided (embedded mode), the gear icon opens the
app-level unified settings dialog instead of the per-surface modal.
Standalone mode is unchanged — no callback means the built-in modal
opens as before.

* Complete settings dialog: all 4 sections, 13 tabs, AI tab

Dialog now has all four sections from the plan:
- General: General (placeholder), Theme, Shortcuts
- Plan Review: Display (placeholder), Saving (placeholder), Labels
  (placeholder), Hooks
- Code Review: Git, Display, Comments, AI
- Integrations: Files (placeholder), Obsidian (placeholder)

7 tabs have full content (Theme, Shortcuts, Hooks, Git, Review Display,
Comments, AI). 6 tabs show placeholder text indicating what settings
will go there — these need the inline content extracted from the
monolithic Settings.tsx in a follow-up.

Reduced motion is already handled globally via theme.css and
tailwindcss-animate.

* Extract settings tabs: General, PlanGeneral, PlanDisplay, Saving

Extracted four tab components from the Settings.tsx monolith into
self-contained files in packages/ui/components/settings/:

- GeneralTab: identity + auto-close (shared across all modes)
- PlanGeneralTab: permission mode (Claude Code) + agent switching
  (OpenCode) — plan-specific, moved out of General
- PlanDisplayTab: TOC, sticky actions, plan width with preview
- SavingTab: plan save toggle/path, default notes app, integration
  quick-nav buttons with onNavigateTab callback

Dialog now has 16 tabs across 4 sections. 11 have full content,
5 remain as placeholders (Labels, Files, Obsidian, Bear, Octarine).

Tab grouping updated per design review:
- Permission Mode and Agent Switching moved from General to Plan Review
- Bear and Octarine added to Integrations section

* Complete all 16 settings tabs — zero placeholders remaining

Extracted remaining tab components from the Settings.tsx monolith:
- LabelsTab: quick annotation labels with emoji, color, AI tips, shortcuts
- FilesTab: file browser enable + directory list management
- ObsidianTab: vault detection, path/folder/filename config, auto-save,
  vault browser toggle
- BearTab: custom tags, tag position, auto-save
- OctarineTab: workspace, folder, auto-save

All 16 tabs across 4 sections now render full settings content:
- General (3): General, Theme, Shortcuts
- Plan Review (5): General, Display, Saving, Labels, Hooks
- Code Review (4): Git, Display, Comments, AI
- Integrations (4): Files, Obsidian, Bear, Octarine

Each extracted tab is self-contained — manages its own state reads/writes
via the existing utility functions and configStore.

* Fix critical settings dialog issues found in eight-agent audit

Critical fixes:
- AISettingsTab now receives required props (providers, selectedProviderId,
  onProviderChange). Fetches /api/ai/capabilities when dialog opens.
- PlanGeneralTab now receives origin from active session so Permission
  Mode and Agent Switching tabs actually render.

Functional fixes:
- Stale state on re-open: mountKey increments when dialog opens, forcing
  Radix Tabs to re-mount tab content so useState initializers re-read
  fresh cookie values.
- Cmd+, now toggles (close if open, open if closed) instead of only
  opening.

Remaining items deferred: Tater Mode toggle in PlanDisplayTab, ThemeTab
preview mode, diffTabSize in ReviewDisplayTab, content gaps in Obsidian/
Octarine/Saving helper text.

* Self-review fixes: stale AI provider, type safety, ObsidianTab fetch

- Re-read aiProviderId from cookies on each dialog open (was stale
  if changed via per-surface settings between opens)
- Remove `as any` cast on origin prop — PlanGeneralTab now accepts
  Origin | string | null
- ObsidianTab no longer depends on useSessionFetch (breaks outside
  SessionProvider). Uses fetchFn prop with globalThis.fetch default.
  Vault detection gracefully falls back to manual input if fetch fails.

* Fix critical issues from second eight-agent audit

1. AI capabilities fetch: route through active session API path
   (/s/:id/api/ai/capabilities) instead of broken root /api/ path.
   Skips fetch when no session is active — AI tab shows empty state.

2. Z-index: dialog overlay and content bumped from z-50 to z-[110],
   above CompletionOverlay's z-[100]. Settings dialog now renders
   on top of everything except toasts.

3. Keyboard shortcuts: unified dialog now shows BOTH plan and code
   review shortcuts with section labels, not just plan mode.

* Full parity: every setting from original Settings.tsx now in extractions

Parity fixes:
- Tater Mode toggle added to PlanDisplayTab (with optional props)
- diffTabSize stepper added to ReviewDisplayTab (was only in popover)
- SavingTab: description text under Default Save Action select restored
- SavingTab: auto-reset effect when integration becomes unavailable
- ObsidianTab: filename format variables hint line restored
- ObsidianTab: filename separator helper text restored
- ObsidianTab: frontmatter preview block restored
- OctarineTab: workspace and folder helper text restored
- LabelsTab: tip editor onFocus cursor handler restored
- PlanGeneralTab: agent warning SVG icon restored
- PlanGeneralTab: stale agent "not found" disabled option restored

Resource cleanup:
- Hidden <Settings> no longer mounts in embedded mode — both plan
  review (skipBuiltInSettings prop) and code review (guard on
  externalOpenSettings) skip rendering when the unified dialog handles it

* Add daemon global settings API — settings work without active sessions

Five new daemon endpoints for settings that previously required a
session-scoped API path:

- GET/POST /daemon/config — read/write ~/.plannotator/config.json
- GET /daemon/git/user — detect git config user.name
- GET /daemon/vaults — detect Obsidian vaults
- GET /daemon/hooks/status — hook file status + PFM reminder

All are thin wrappers around existing functions in packages/shared/
with no session context needed.

Frontend routing: added globalFetchBase fallback to apiFetch. When
__PLANNOTATOR_API_BASE__ is unset (landing page, no session), config
writes route through /daemon/config. Session base still takes
precedence when set.

Settings dialog: fetches gitUser from /daemon/git/user on open,
initializes configStore from /daemon/config, passes daemon-routed
fetch to ObsidianTab and HooksTab so vault detection and hook status
work from the landing page.

* Fix ObsidianTab vault URL: accept both /daemon/vaults and /daemon/obsidian/vaults

* Fix theme preview mode and slow theme switching with keep-alive

Theme preview: wired onPreview to ThemeTab in unified dialog. Clicking
"Launch Preview Mode" hides the dialog and opens a bottom drawer with
a compact ThemeTab. Escape or Done button returns to the dialog.

Theme switching performance: hidden keep-alive surfaces now skip color
transitions entirely via [style*="visibility: hidden"] * { transition-
duration: 0s }. Only visible content animates, eliminating the lag from
thousands of elements transitioning simultaneously.

* Add performance scope documents: global keyboard registry + configStore Zustand migration

* Move performance scope docs to backlog directory

* Document performance findings: 15 identified issues ranked by impact

* Update performance findings: 22 issues across 4 tiers, prioritized for normal use

* Add 3 new findings from agent sweep: layout thrashing, context invalidation, getComputedStyle

* Add memory leak findings: draft maps, uncancelled rAF, WS subscription accumulation

* Final sweep: 39 total findings incl bundle size, static imports, backdrop-blur, monolith components

* Performance Phase 1: stop hidden sessions from degrading active session

Fix 1 — React.memo on SessionSurface: Layout re-renders (sidebar
toggle, dialog open, session switch) no longer cascade into every
mounted session's component tree. The bootstrap prop is reference-
stable so memo always bails out for hidden sessions.

Fix 3 — Scope document.querySelector to session container:
- StickyHeaderLane: new containerRef prop, queries within the session's
  root instead of the global document. Prevents hidden sessions from
  attaching ResizeObservers to the active session's elements.
- TableOfContents: scopes block-id query to scrollViewport instead of
  document. Prevents hidden session TOC clicks from scrolling the
  active session.
- PlanCleanDiffView: new containerRef prop for diff-block-index query.
  Prevents hidden session annotation selections from highlighting
  blocks in the active session.

Fix 4 — Gate document-level mutations on visibility:
- CSS custom properties (--diff-font-override etc.) now set on
  rootRef.current instead of document.documentElement. Each session
  scopes its own font/tab-size vars. No more global style recalc
  from hidden sessions writing to :root.
- document.title gated with isVisible() in both surfaces. Hidden
  sessions no longer overwrite the active session's title.

* Self-review fixes: PlanCleanDiffView self-scoping, font-size CSS selectors

- PlanCleanDiffView now has its own rootRef on its wrapper div, so the
  querySelector for diff-block-index elements scopes to its own tree
  without needing containerRef threaded from the parent
- CSS font-size-override selectors changed from :root[style*="..."]
  to .has-font-size-override class — the :root selectors broke when
  CSS vars moved from document.documentElement to rootRef.current
- Cleanup removes the class on effect teardown

* Fix tab size not applying to diffs and title not updating on session switch

Tab size: moved from CSS variable on rootRef (which didn't penetrate
Pierre's shadow DOM) to direct unsafeCSS injection via usePierreTheme,
matching how font-family and font-size already work.

Title: replaced static isVisible callback (empty deps, never re-triggered)
with useSessionVisible hook that uses MutationObserver to reactively
detect when Layout.tsx toggles the parent's visibility style.

* Use content-visibility: hidden on inactive sessions to skip layout/paint

The browser was doing full layout and style recalc on every hidden
session's DOM (60-120k nodes with 3+ sessions). content-visibility: hidden
tells the browser to skip all rendering work on inactive subtrees while
preserving DOM state, scroll positions, and React component state.

Also runs oxfmt on frontend files to fix pre-existing formatting drift.

* Scroll to annotation line when clicking sidebar comment in all-files view

Previously only scrolled to the file header. Now finds the
[data-annotation-id] element and scrolls to it directly, with a
retry loop for lazy-mounted diffs and file header fallback.

* Add Zustand review store with per-session scoping

Introduces a Zustand store for the code review surface, replacing
annotation useState calls with store state. Panels can now subscribe
to specific slices via selectors instead of re-rendering on every
unrelated state change through the ReviewStateContext god object.

Phase 1: annotations slice (hot path), diff-options slice, files slice.
DiffHunkPreview migrated as first panel consumer. ReviewStateContext
stays alive for unmigrated panels during the transition.

* Fix deleted annotations reappearing after refresh

When all annotations were deleted, the draft auto-save skipped the
save entirely, leaving the stale draft on the server. On refresh it
restored the deleted annotations. Now tracks whether a draft exists
on the server and issues a DELETE when annotations drop to zero.

* Stabilize callbacks via getState() and memo FileTreeNodeItem

Migrate files and activeFileIndex to store-owned state (remove sync
bridge). Stabilize 7 callbacks + keyboard handler by reading
pendingSelection, files, activeFileIndex, externalAnnotations,
selectedAnnotationId, and allAnnotations from storeApi.getState()
instead of closing over them. Callbacks now have stable references
that don't recreate on every hover or file switch.

Wrap FileTreeNodeItem in React.memo — 531 instances were re-rendering
29 times each (15,399 total, 1,202ms) due to parent cascades.

Baseline: 55% of render time (4,825ms) was full-tree cascades
triggered by ReviewApp. These changes eliminate the callback
instability that caused most of those cascades.

* Add React.memo to shared UI components and stabilize plan review props

Wrap BlockRenderer, InlineMarkdown, CodeFileLink, and TableBlock in
React.memo. These render hundreds of times per plan/review session
due to parent cascades — profiler showed 778 BlockRenderer renders
and 888 InlineMarkdown renders in a single session. Memo prevents
re-renders when the block content and callbacks haven't changed.

Stabilize plan review App.tsx props to Viewer: replace inline arrow
functions (onPlanDiffToggle) with useCallback, replace inline
linkedDocInfo object with useMemo. These created new references on
every render, defeating any memo on child components.

* Fix backLabel reference-before-initialization in plan review

The linkedDocInfo useMemo was placed above the backLabel variable
it depends on, causing a crash on plan session load. Moved the
useMemo below backLabel's declaration.

* Unified frontend: Git Dashboard, PR listing, sidebar redesign, and settings cleanup (#765)

* Add PR listing, multi-select launch, stacked PR grouping, and project management to frontend landing page

- Fix worktree project registration: session factory now uses addProject() instead of registerProject() so worktrees nest under parent projects
- Fix directory typeahead: handle partial paths by splitting into parent dir + prefix filter
- Add daemon endpoint GET /daemon/projects/prs for listing PRs via GitHub/GitLab CLI
- Add PR list with stacked PR detection using headBranch/baseBranch chain matching
- Add multi-select for PRs and worktrees with parallel session launch via Promise.allSettled
- Restructure worktrees from badge pills to row layout matching PR list style
- Add tabbed expansion panel (PRs default, Worktrees) under each project
- Add shared formatSessionLabel() for clean display names across sidebar, landing page, and toasts
- Add right-click context menu to remove projects with session cancellation and history cleanup
- Add PullRequestIcon with state-based coloring (open/merged/closed)

* Clean up settings dialog: proper header, version info, compact display tab layout

- Replace absolute-positioned close button with dedicated header bar to prevent toggle overlap
- Remove settings cog icon, add version number and send feedback link
- Rewrite Code Review Display tab with grouped sections (Typography, Layout, Options)
- Replace font size slider with +/- stepper matching tab size pattern
- Make segmented controls inline with labels for compact layout
- Add live preview showing both font family and size together
- Fix Theme tab spacing: add divider and gap between Mode and Theme sections
- Move Line Backgrounds toggle to end of Options (sub-setting at bottom)

* Git dashboard, settings cleanup, sidebar redesign, and PR data pipeline

- Add PRDetailedListItem type and fetchPRDetailedList for dashboard-specific PR data
- Add daemon endpoint GET /daemon/projects/prs/detailed with 30s cache
- Add git-dashboard-store (Zustand) with parallel multi-project fetch and dedup
- Build Git Dashboard with PRRow, PRGroup, MetricCards components
- Dashboard groups PRs into Open/Draft/Recently Merged with scroll-to navigation
- Clicking a PR row launches a review session via createReviewSession
- Add CSS translateX slide transition between landing page and dashboard
- Clean up settings dialog: proper header bar, version info, send feedback link
- Rewrite Code Review Display tab with grouped sections and compact inline controls
- Fix Theme tab spacing between Mode and Theme sections
- Redesign sidebar: sprite mascot header, Instrument Sans brand font, version display
- Remove session status dots/checkmarks, move mode icons to group headers
- Compact sidebar session rows (text-xs, h-7) with alignment spacers
- Embed sidebar trigger in landing page card instead of dedicated nav bar
- Add right-click context menu for project removal with session/history cleanup
- Fix directory typeahead prefix filtering for partial path input
- Fix worktree project registration via addProject() instead of registerProject()
- Add multi-select session launch with parallel Promise.allSettled
- Add stacked PR grouping via headBranch/baseBranch chain detection
- Add shared formatSessionLabel() for clean display across sidebar/landing/toasts
- Deduplicate PRs across projects sharing the same remote

* Add hover-triggered peek sidebar when sidebar is closed

- Extract AppSidebarContent for reuse between real sidebar and peek
- SidebarPeek renders a floating panel on left-edge hover (80vh, centered)
- Backdrop overlay fades in at bg-black/30 behind the panel
- Panel slides in/out at 150ms, backdrop at 200ms
- Uses bg-sidebar token for consistent background with real sidebar
- Remove session tooltip hovers
- Only active when sidebar is collapsed

* Remove unused asset files (banners, mascot, sprite backups, index.html)

* Address PR review findings: security fix, dedup, lazy loading, error surfacing

- Fix path traversal: sanitize project name before use in rmSync path
- Switch project deletion from name-based to cwd-based identification
- Deduplicate archive launches by cwd when multiple selections share a project
- Gate dashboard PR fetch on visibility (only fetch when dashboard slide is active)
- Gate worktree fetch on expanded state (don't shell out until user expands)
- Track project count in dashboard store for cache invalidation on add/remove
- Surface auth and CLI errors in dashboard instead of showing misleading empty state
- Consolidate duplicate PR ref resolution into single handler for both endpoints
- Delete unused carousel.tsx and remove motion dependency
- Move @radix-ui/react-context-menu from devDependencies to dependencies

* Tighten path sanitization: reject dot-only names in history cleanup

* Fix review findings: timer leak, stale tabs, blank dashboard, clear on remove, path guard

- Fix SidebarPeek timer leak: clear existing timeout before setting new one in hide()
- PR tabs now refetch after 30s instead of being permanently cached
- Dashboard isEmpty derived from visible groups, not raw array (fixes blank state for closed-only repos)
- Dashboard clears stale PRs when all projects are removed
- Defense-in-depth: verify resolved rmSync path is inside history root before deleting
- Fix handleRemove missing project.cwd in useCallback dependency array

* Move tater mode to configStore and fix formatting from L10 merge

Tater mode was useState inside plan review App.tsx — unreachable from
the unified settings dialog. Now lives in the global configStore as a
cookie-backed setting. PlanDisplayTab reads it directly via
useConfigValue, no props needed from AppSettingsDialog.

Also runs oxfmt on files from the L10 merge (git dashboard, sidebar,
settings dialog).

* Address PR review findings: stale closures, dead code, missing deps

- Fix stale closure in applyPRResponse: read currentPath before setFiles
- Deduplicate allAnnotations: App.tsx useMemo now calls selectAllAnnotations
- Remove dead fields from files slice (viewedFiles, stagedFiles, reviewBase,
  activeDiffBase and their setters — never called, data still flows through
  ReviewStateContext)
- Wrap default ReviewApp export in ReviewStoreProvider
- Add missing daemon endpoints to AGENTS.md
- Add dependency array to SavingTab useEffect (was firing every render)
- Add activeSessionId to AppSettingsDialog AI capabilities fetch deps

* Fix fetchDiffSwitch stale closure + unstable deps, correct AGENTS.md allowlist

- Read currentPath from getState() before setFiles in preserveFile
  branch (same pattern as applyPRResponse fix)
- Remove files and activeFileIndex from fetchDiffSwitch dep array —
  last unstable callback, now reads from getState() consistently
- Fix AGENTS.md: POST /daemon/config allows conventionalComments and
  conventionalLabels, not legacyTabMode and verifyAttestation

* Fix L10 bugs: stale selections, PR error clearing, dashboard cache

- Clean up selections when projects are removed — prevents stale
  selections from enabling launch buttons for deleted projects
- Clear PR error on successful fetch — errors no longer stick after
  the user fixes their CLI setup
- Dashboard cache invalidates on project identity (cwd set), not just
  count — swapping projects within the same count now triggers refresh
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