Skip to content

Polish the desktop app launcher, sign-in, chat tools, and workspace chrome - #766

Merged
alexeyzimarev merged 15 commits into
mainfrom
app-ux-enhancements
Sep 5, 2026
Merged

alexeyzimarev merged 15 commits into
mainfrom
app-ux-enhancements

Conversation

@nortonandreev

@nortonandreev nortonandreev commented Sep 4, 2026 •

Copy link
Copy Markdown
Contributor

No GitHub issue — no Linear id for this PR.

What & why

Desktop app UX pass: launcher chips/flyouts and Start tips, daemon recovery in a banner above the launch card, clearer sign-in (copy, browser fallback, Enter to start), long-repo headline layout, chat tool callouts with status greens, and workspace identity as a muted subtitle. Theme tokens split primary CTAs from success green and lift muted/faint contrast on dark canvas.

Where to look

LauncherPaneView / HomeViewModel (chips, recovery, Start tips, repo defaults); ChatTabView / ChatItems (tool groups); WorkspaceView IdentitySubtitle beside main's work-context column. Easy to miss: App.axaml.cs keeps _launch so reauth invalidates the same client ServerClients wraps.

Verification

  • dotnet build src/Capacitor.App/Capacitor.App.csproj — 0 warnings, 0 errors (after rebase onto main including Add the work-context sidebar to the desktop session workspace #763)
  • dotnet run --project test/Capacitor.App.Tests.Unit/Capacitor.App.Tests.Unit.csproj -- --treenode-filter "/*/*/HomeViewModelTests/*" — passed
  • dotnet run --project test/Capacitor.App.Tests.Unit/Capacitor.App.Tests.Unit.csproj -- --treenode-filter "/*/*/SignInStepViewModelTests/*" — passed
  • dotnet run --project test/Capacitor.App.Tests.Unit/Capacitor.App.Tests.Unit.csproj -- --treenode-filter "/*/*/HostedHarnessCatalogTests/*" — passed
  • Manual: Start tips (no repo / disconnected); repo flyout; sign-in idle + browser-wait; tool callouts; workspace subtitle

Visuals

Screenshot 2026-09-04 at 18 51 31 Screenshot 2026-09-04 at 18 51 26 Screenshot 2026-09-04 at 18 51 44

@nortonandreev nortonandreev self-assigned this Sep 4, 2026
@nortonandreev nortonandreev changed the title Polish the desktop app launcher, sign-in, and theme tokens Polish the desktop app launcher, sign-in, chat tools, and workspace chrome Sep 4, 2026
@nortonandreev

nortonandreev commented Sep 4, 2026 •

Copy link
Copy Markdown
Contributor Author

Full change list

Theme / chrome

  • Split primary CTA tokens (KcapPrimary*) from success/status green (KcapSuccess*) so Start and selection no longer share one green.
  • Lift KcapMuted / KcapFaint so secondary copy meets usable contrast on canvas through border.
  • Force dark Fluent theme variant; pin chip / primary button hover and disabled chrome so Fluent’s PART_ContentPresenter pointer-over no longer wipes custom fills (light-on-light).
  • Placeholder text on embedded text boxes uses muted brush (launcher goal + chat composer readable on dark).
  • Soft pulse style for in-flight tool rows (Border.toolRunning).

Launcher / daemon recovery

  • Chip labels, repo flyout harness badges, and Start disabled tips (repo missing and/or connection blocked) with ToolTip.ShowOnDisabled.
  • Connection / daemon recovery lives in a warning banner above the launch card (not inside the composer).
  • One primary action at a time: Start daemon when the daemon looks down; Reconnect when connecting or skewed — never both.
  • One banner line (BannerMessage): a start/lifecycle message wins over the generic unreachable notice (sidebar already shows Unreachable); warning styling, not danger red.
  • Known mutation attention/storage tokens map to actionable human copy; unknown tokens stay log-only (no opaque “needs attention (token)” banner). cli_below_floor names the app↔CLI floor, not “too old for the daemon.”
  • Connection notices when there is no start failure yet: server lost, sign-in expired, daemon down / incompatible, finishing sign-in.
  • Prefer a recent real repo over the scratch menu row when choosing a default.
  • Dedup repo paths in the recent list / related surfaces.
  • Split headline: fixed question + muted/ellipsis repo subtitle; two-row footer so long paths don’t crush chips + Start.
  • Enter starts a session when the launcher form is ready.
  • Window sizing kept compatible with the work-context sidebar (MinWidth="1200", MinHeight="560").

Sign-in

  • Idle / busy copy polish; bottom browser-fallback panel with selectable URL plus open/copy.
  • Clearer feedback while the browser flow runs; punctuation/copy cleanup on error and unusable-ID strings.
  • Reauth path notifies home and server clients; launch client invalidate kept for the same instance ServerClients owns.

Workspace / session chrome

  • Declutter header: drop vendor chip and harness/transport meta (those live in the right pane); subtitle is checkout only (RepoLabelText).
  • Title fallback is the repo leaf only.
  • Layout preserved next to main’s work-context sidebar (Grid *,400 + WorkContextView).

Work-context sidebar (About this work)

Relative to main’s pane (#763):

  • Section headers (WHO'S ON IT, SESSION, parts) get real padding, hover hit area, and right-docked chevron / SOON.
  • More space under hovered section headers so summary/facts aren’t tight to the highlight.
  • Session fact rows: labels and values vertically centered; wider label column gutter.
  • Header refresh: proper iconButton hit target; “ABOUT THIS WORK” and refresh share a vertical center line.
  • Drag-to-move only on the eyebrow (and never from buttons), so refresh clicks aren’t stolen.
  • Refresh stays enabled while a read is in flight and queues one follow-up instead of greying out with no feedback.
  • Disabled refresh shows why via ToolTip.ShowOnDisabled (Waiting for the session ID / Refreshing… / Refresh).
  • User-facing acronyms normalized (session ID, PID in related daemon copy).

Chat

  • Tool callouts: kind label, wider cards, selectable detail text.
  • Status pill on top for a lone in-flight call; grouped runs fold into a peek summary when there are two or more settled calls.
  • Status greens aligned to connected / disrupted status colors.
  • Spacing / pulse polish for live tool rows.
  • When a session ends, hide the composer and Send (keep the “This session has ended” line) and disable Stop as soon as status is Completed/Failed, not only after the agent leaves the snapshot.
  • Headless smoke: second render tick + center hit + larger tool-summary hit area so fold-expand clicks stay reliable on Windows CI.

Activity / tray / rail (supporting)

  • Activity status coloring aligned with the same greens.
  • Tray / rail / related view-model tweaks tied to repo labeling and chrome declutter.

Tests / hygiene

  • Smoke and unit coverage for launcher headline controls, Start tips, exclusive Start/Reconnect, single banner line, human attention copy, sign-in, tool groups, workspace subtitle, MainWindow sizing, work-context refresh queueing.
  • Unusable-ID assert pinned to HomeViewModel.UnusableIdMessage.

@nortonandreev
nortonandreev marked this pull request as ready for review September 4, 2026 16:24
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Polish desktop launcher, sign-in, chat tools, and workspace chrome

✨ Enhancement 🐞 Bug fix 🧪 Tests 🕐 40+ Minutes

Grey Divider

AI Description

• Refines launcher, sign-in, chat tools, activity, and workspace presentation.
• Unifies daemon recovery and refreshes authenticated clients after reauthorization.
• Normalizes repository identity and expands behavioral and headless UI coverage.
Diagram

graph TD
  U["Desktop user"] --> L["Launcher pane"] --> H["Home state"] --> D["Daemon lifecycle"]
  H --> C["Launch client"]
  U --> S["Sign-in flow"] --> H
  U --> W["Workspace views"] --> T["Chat tools"]
Loading
High-Level Assessment

The approach is appropriate for a UX-focused pass: it retains existing Avalonia and ReactiveUI boundaries, reuses MainWindow recovery commands in the launcher, and invalidates the existing launch client rather than introducing parallel authentication state. Replacing the code-built flyouts with a new reusable control was considered, but would add abstraction and migration risk beyond this PR's scope.

Files changed (52) +2342 / -708

Enhancement (26) +1523 / -538
App.axamlExpand the dark UX token and control style system +74/-8

Expand the dark UX token and control style system

• Forces the dark theme, improves muted-text contrast, and separates primary-action colors from success colors. Adds shared flyout, chip, primary, ghost, embedded-field, and running-tool styles.

src/Capacitor.App/App.axaml

DaemonLifecycleController.csReport actionable daemon start progress +24/-10

Report actionable daemon start progress

• Adds immediate and terminal feedback for start and reconnect attempts, including mutation success and failure. Also standardizes daemon PID wording.

src/Capacitor.App/Services/DaemonLifecycleController.cs

HostedHarnessCatalog.csStandardize launcher option labels +20/-3

Standardize launcher option labels

• Introduces shared sentence-case effort labels and consistently displays the harness-controlled sentinel as “Default.” Updates fallback tile contrast.

src/Capacitor.App/Services/HostedHarnessCatalog.cs

ActivityViewModel.csShorten activity timestamps with full hover detail +19/-13

Shorten activity timestamps with full hover detail

• Projects a compact local timestamp for activity rows while retaining the full local date and time in a tooltip value.

src/Capacitor.App/ViewModels/ActivityViewModel.cs

ChatItems.csModel polished tool call cards and summaries +75/-4

Model polished tool call cards and summaries

• Adds detail-first row text, explicit running state, lone-call chrome, and folded summary previews. Single calls remain visible while multi-call groups can collapse settled rows.

src/Capacitor.App/ViewModels/ChatItems.cs

ChatTabViewModel.csSimplify chat composer guidance +5/-5

Simplify chat composer guidance

• Removes the redundant harness name from the ready-state composer hint while preserving availability-specific guidance.

src/Capacitor.App/ViewModels/ChatTabViewModel.cs

HomeViewModel.csUnify launcher recovery, tips, and repository defaults +202/-23

Unify launcher recovery, tips, and repository defaults

• Combines connection and lifecycle feedback into one actionable banner and exposes shared start/reconnect commands. Adds disabled-start tips, post-sign-in reconnect state, normalized repository deduplication, and recent-repository selection.

src/Capacitor.App/ViewModels/HomeViewModel.cs

MainWindowViewModel.csShare one daemon recovery state with the launcher +103/-26

Share one daemon recovery state with the launcher

• Makes Start and Reconnect mutually exclusive, publishes immediate click feedback, and maps raw attach reasons to actionable messages. Shares commands and lifecycle messages with HomeViewModel and hides the built-in default profile label.

src/Capacitor.App/ViewModels/MainWindowViewModel.cs

DaemonStepViewModel.csStandardize daemon PID copy +2/-2

Standardize daemon PID copy

• Capitalizes PID consistently in manual-daemon onboarding messages.

src/Capacitor.App/ViewModels/Onboarding/DaemonStepViewModel.cs

SignInStepViewModel.csClarify sign-in progress, success, and retry states +69/-27

Clarify sign-in progress, success, and retry states

• Adds browser-wait guidance, concise ready-state copy, success refresh feedback, and contextual primary-action labels. Deduplicates error logging and formats error details for display.

src/Capacitor.App/ViewModels/Onboarding/SignInStepViewModel.cs

ToolSummary.csAdd concise tool category labels +16/-0

Add concise tool category labels

• Maps tool categories to short nouns used by lone-call card headers.

src/Capacitor.App/ViewModels/ToolSummary.cs

WorkContextViewModel.csQueue refreshes and explain refresh availability +30/-4

Queue refreshes and explain refresh availability

• Keeps refresh enabled during reads and queues one follow-up request when clicked in flight. Adds contextual tooltip text for reading and unavailable states.

src/Capacitor.App/ViewModels/WorkContextViewModel.cs

ChatTabView.axamlRender tool calls as status-aware cards +85/-42

Render tool calls as status-aware cards

• Introduces copyable detail-first tool rows, lone-call headers, foldable multi-call summaries, and pulsing running indicators. Aligns permission actions and Send with the primary CTA palette.

src/Capacitor.App/Views/ChatTabView.axaml

Converters.csAlign outcome colors with shared status colors +12/-9

Align outcome colors with shared status colors

• Maps activity and tool outcomes to the application’s canonical connected and disrupted colors using immutable tool-status brushes.

src/Capacitor.App/Views/Converters.cs

HomeView.axaml.csClarify repository chip labels and count visibility +18/-6

Clarify repository chip labels and count visibility

• Prefixes repository values with their setting name and adds an inverse count converter for content-driven visibility.

src/Capacitor.App/Views/HomeView.axaml.cs

LauncherPaneView.axamlRecompose launcher headline, banner, and controls +125/-79

Recompose launcher headline, banner, and controls

• Moves daemon and sign-in recovery into a banner above the launch card. Splits the fixed headline from the repository subtitle, separates long repository chips from settings, and adds contextual Start tooltips.

src/Capacitor.App/Views/LauncherPaneView.axaml

LauncherPaneView.axaml.csPolish launcher flyouts and Enter-to-start +184/-65

Polish launcher flyouts and Enter-to-start

• Replaces Fluent menu flyouts with dark token-based picker panels for repositories, effort, and permissions. Handles Enter in the goal field, improves option labeling, and adds long-repository tooltip support.

src/Capacitor.App/Views/LauncherPaneView.axaml.cs

MainWindow.axamlMove recovery into launcher and polish activity +91/-58

Move recovery into launcher and polish activity

• Removes duplicate daemon recovery chrome from the window header. Rebuilds the Activity flyout with aligned columns, scrolling, compact timestamps, tooltips, and a clearer empty state.

src/Capacitor.App/Views/MainWindow.axaml

MarkdownBlocks.csUse the shared success color for markdown links +1/-1

Use the shared success color for markdown links

• Moves interactive markdown link coloring from the removed accent token to the success token.

src/Capacitor.App/Views/MarkdownBlocks.cs

SignInStepView.axamlRedesign the complete sign-in experience +249/-98

Redesign the complete sign-in experience

• Reorganizes status, browser fallback, progress, tenant selection, and workspace creation into clearer dark-themed sections. Adds selectable and copyable browser URLs plus consistent primary and secondary actions.

src/Capacitor.App/Views/Onboarding/SignInStepView.axaml

SignInStepView.axaml.csCopy the browser sign-in URL +10/-0

Copy the browser sign-in URL

• Adds clipboard handling for the sign-in fallback link.

src/Capacitor.App/Views/Onboarding/SignInStepView.axaml.cs

SessionRailView.axamlStabilize session rail hover styling +14/-2

Stabilize session rail hover styling

• Pins hover and pressed states to dark application tokens and restyles the New session action.

src/Capacitor.App/Views/SessionRailView.axaml

SignInWindow.axamlResize and theme the reauthentication window +5/-2

Resize and theme the reauthentication window

• Uses a taller fixed-size dark window with increased content margins for the redesigned sign-in flow.

src/Capacitor.App/Views/SignInWindow.axaml

WorkContextView.axamlPolish work-context sections and refresh control +68/-26

Polish work-context sections and refresh control

• Adds larger interactive section headers, consistent hover states, and an accessible refresh hit target with contextual tooltip behavior. Tightens spacing and aligns session facts.

src/Capacitor.App/Views/WorkContextView.axaml

WorkspaceView.axamlFold workspace identity into a muted subtitle +21/-24

Fold workspace identity into a muted subtitle

• Removes redundant harness chrome and displays checkout identity as a muted subtitle beneath the title. Also stabilizes tab hover colors and aligns terminal actions with the primary palette.

src/Capacitor.App/Views/WorkspaceView.axaml

OAuthLoginFlow.csMake wrong-workspace authentication errors actionable +1/-1

Make wrong-workspace authentication errors actionable

• Rewords the OAuth workspace mismatch error for the desktop sign-in flow and removes CLI-specific retry instructions.

src/Capacitor.Cli.Core/Auth/OAuthLoginFlow.cs

Bug fix (5) +134 / -25
App.axaml.csRefresh application clients after reauthentication +80/-14

Refresh application clients after reauthentication

• Retains the launch client so successful reauthentication can invalidate its authenticated hub and restart attachment. Also routes lifecycle attention into launcher recovery and replaces mutation tokens with actionable user-facing copy.

src/Capacitor.App/App.axaml.cs

ServerLaunchClient.csInvalidate stale authenticated launch connections +14/-0

Invalidate stale authenticated launch connections

• Adds gated hub invalidation so a launch after reauthentication rebuilds its access-token provider without racing an in-flight launch.

src/Capacitor.App/Services/ServerLaunchClient.cs

SessionRailViewModel.csNormalize repository grouping keys +4/-3

Normalize repository grouping keys

• Normalizes checkout and repository roots so trailing separators cannot split one repository into duplicate rail groups.

src/Capacitor.App/ViewModels/SessionRailViewModel.cs

TrayModels.csCentralize trailing-separator path identity +28/-7

Centralize trailing-separator path identity

• Adds path normalization and a platform-aware comparer that ignores trailing directory separators. Checkout formatting and leaf extraction now use the normalized identity.

src/Capacitor.App/ViewModels/TrayModels.cs

WorkContextView.axaml.csProtect work-context controls from window dragging +8/-1

Protect work-context controls from window dragging

• Prevents header drag handling when the pointer originates from the refresh button or another button.

src/Capacitor.App/Views/WorkContextView.axaml.cs

Refactor (1) +4 / -20
WorkspaceViewModel.csReduce workspace header identity projections +4/-20

Reduce workspace header identity projections

• Removes redundant vendor and transport badges from the workspace header, leaving the session title and checkout subtitle while work context carries technical identity.

src/Capacitor.App/ViewModels/WorkspaceViewModel.cs

Tests (19) +680 / -125
ActivityViewModelTests.csVerify compact and tooltip activity timestamps +4/-2

Verify compact and tooltip activity timestamps

• Updates activity projection assertions for short display times and full hover timestamps.

test/Capacitor.App.Tests.Unit/ActivityViewModelTests.cs

AppMutationLaneWiringTests.csVerify human-readable mutation recovery messages +55/-19

Verify human-readable mutation recovery messages

• Covers actionable copy for known mutation outcomes and confirms unknown wire tokens remain log-only while still being acknowledged.

test/Capacitor.App.Tests.Unit/AppMutationLaneWiringTests.cs

ChatComposerTests.csUpdate composer and default-model expectations +8/-8

Update composer and default-model expectations

• Verifies availability-only composer hints and the standardized “Default” model label.

test/Capacitor.App.Tests.Unit/ChatComposerTests.cs

ChatTabViewSmokeTests.csExercise polished chat tool cards +101/-21

Exercise polished chat tool cards

• Adds headless coverage for lone and grouped tool cards, detail previews, status pills, permission states, and running animation. Hardens synthetic summary clicks across platforms.

test/Capacitor.App.Tests.Unit/ChatTabViewSmokeTests.cs

DaemonLifecycleControllerTests.csVerify daemon start and reconnect feedback +4/-0

Verify daemon start and reconnect feedback

• Asserts that already-running and detached-start paths publish visible follow-up status.

test/Capacitor.App.Tests.Unit/DaemonLifecycleControllerTests.cs

HomeViewModelTests.csCover launcher recovery and repository selection +90/-8

Cover launcher recovery and repository selection

• Tests trailing-separator deduplication, scratch visibility, recent-repository defaults, banner precedence, contextual Start tips, and post-sign-in reconnect messaging.

test/Capacitor.App.Tests.Unit/HomeViewModelTests.cs

HomeViewSmokeTests.csExercise launcher layout and keyboard behavior +162/-7

Exercise launcher layout and keyboard behavior

• Verifies the fixed headline and repository subtitle, recovery controls, disabled Start tooltip, and Enter-to-start behavior with and without a repository.

test/Capacitor.App.Tests.Unit/HomeViewSmokeTests.cs

HostedHarnessCatalogTests.csVerify standardized default and effort labels +15/-2

Verify standardized default and effort labels

• Covers sentence-case effort labels, Max mapping, unknown-token fallback, and consistent “Default” model wording.

test/Capacitor.App.Tests.Unit/HostedHarnessCatalogTests.cs

MainWindowSmokeTests.csVerify the unified launcher recovery banner +24/-17

Verify the unified launcher recovery banner

• Updates window smoke coverage to ensure connection and start failures share one non-stacking banner body.

test/Capacitor.App.Tests.Unit/MainWindowSmokeTests.cs

MainWindowViewModelTests.csCover mutually exclusive daemon recovery states +89/-22

Cover mutually exclusive daemon recovery states

• Tests profile-label suppression, friendly attach reasons, immediate Start/Reconnect feedback, failed reconnect settlement, and lifecycle-attention routing.

test/Capacitor.App.Tests.Unit/MainWindowViewModelTests.cs

ReauthCompositionTests.csUpdate reauthentication ready-state expectation +1/-1

Update reauthentication ready-state expectation

• Asserts that the sign-in status headline now displays only the configured server destination.

test/Capacitor.App.Tests.Unit/ReauthCompositionTests.cs

SessionRailViewModelTests.csVerify normalized repository rail grouping +20/-0

Verify normalized repository rail grouping

• Ensures repository paths differing only by a trailing separator share one repository and worktree group.

test/Capacitor.App.Tests.Unit/SessionRailViewModelTests.cs

SignInStepViewModelTests.csVerify polished sign-in feedback states +7/-5

Verify polished sign-in feedback states

• Covers success refresh detail, hidden post-success action, deduplicated formatted errors, and revised ready-state copy.

test/Capacitor.App.Tests.Unit/SignInStepViewModelTests.cs

ToolGroupItemTests.csCover lone and folded tool group behavior +57/-0

Cover lone and folded tool group behavior

• Tests category chips, detail-first row text, capped folded previews, running state, and lone-call status placement.

test/Capacitor.App.Tests.Unit/ToolGroupItemTests.cs

ToolSummaryTests.csVerify tool category chip labels +8/-0

Verify tool category chip labels

• Adds coverage for concise category labels and the generic tool fallback.

test/Capacitor.App.Tests.Unit/ToolSummaryTests.cs

WorkContextViewModelTests.csVerify queued work-context refreshes +27/-2

Verify queued work-context refreshes

• Confirms refresh remains executable during reads and schedules exactly one follow-up operation.

test/Capacitor.App.Tests.Unit/WorkContextViewModelTests.cs

WorkspaceNavigationTests.csShare the canonical unusable-session message +1/-1

Share the canonical unusable-session message

• References HomeViewModel’s message constant instead of duplicating launch failure copy.

test/Capacitor.App.Tests.Unit/WorkspaceNavigationTests.cs

WorkspaceViewModelTests.csUpdate streamlined workspace identity assertions +6/-9

Update streamlined workspace identity assertions

• Removes vendor and transport badge expectations and verifies the title now falls back to the repository leaf alone.

test/Capacitor.App.Tests.Unit/WorkspaceViewModelTests.cs

WorkspaceViewSmokeTests.csTrack the renamed workspace subtitle control +1/-1

Track the renamed workspace subtitle control

• Updates workspace smoke control discovery for the consolidated identity subtitle.

test/Capacitor.App.Tests.Unit/WorkspaceViewSmokeTests.cs

Other (1) +1 / -0
.gitignoreIgnore local development workspace files +1/-0

Ignore local development workspace files

• Adds the '.dev/' directory to repository-wide ignore rules.

.gitignore

@qodo-code-review

qodo-code-review Bot commented Sep 4, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Default overwrites repository choice ✓ Resolved 🐞 Bug ≡ Correctness
Description
EnsureDefaultRepositoryAsync checks for an empty selection only before awaiting repository
discovery, then unconditionally applies the discovered default. If the user selects a repository
while that lookup is suspended, the startup task overwrites the explicit choice and restores the
wrong harness.
Code

src/Capacitor.App/ViewModels/HomeViewModel.cs[R465-467]

+        if (SelectedRepoPath.Length > 0) return;
+        if (await PreferRecentRepositoryAsync() is not { Length: > 0 } recent) return;
+        await SelectRepositoryAsync(recent);
Relevance

●●● Strong

A closely matching HomeViewModel persistence race was accepted in the same launcher work.

PR-#653

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The guard runs before PreferRecentRepositoryAsync, which awaits the production repository store,
while picker callbacks can update the selection during that suspension. The subsequent unconditional
call to SelectRepositoryAsync assigns the discovered path and its harness regardless of the newer
user choice.

src/Capacitor.App/ViewModels/HomeViewModel.cs[310-312]
src/Capacitor.App/ViewModels/HomeViewModel.cs[464-487]
src/Capacitor.App/ViewModels/HomeViewModel.cs[492-496]
src/Capacitor.App/Views/LauncherPaneView.axaml.cs[110-114]
src/Capacitor.Cli.Core/Config/RepoPathStore.cs[22-29]
src/Capacitor.App/App.axaml.cs[766-772]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Prevent asynchronous default-repository discovery from overwriting a repository explicitly selected while the lookup was in progress.

## Issue Context
The constructor starts default selection asynchronously, and the real repository provider performs asynchronous file I/O. `EnsureDefaultRepositoryAsync` must only commit its result if the selection is still empty after discovery; concurrent default-selection calls should also be serialized or made idempotent.

## Fix Focus Areas
- src/Capacitor.App/ViewModels/HomeViewModel.cs[310-312]
- src/Capacitor.App/ViewModels/HomeViewModel.cs[464-487]
- src/Capacitor.App/ViewModels/HomeViewModel.cs[492-496]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Unreachable back-compat shape documented ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
The PR adds a Back-compat comment and overload for previously classified availability without
identifying any persisted or supported source that still requires this shape. Repository search
finds no callers of this overload, so the deprecated compatibility shape is not observable.
Code

src/Capacitor.App/ViewModels/HomeViewModel.cs[385]

+    /// Back-compat for callers that already classified availability.
Relevance

●●● Strong

The team recently accepted removing unsupported historical metadata from comments and preserving
only observable behavior.

PR-#666
PR-#653

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Rule 2897945 permits deprecated-shape comments only when they identify a concrete source that can
still produce the old form. The added comment only refers generically to existing callers, while the
overload has no call sites in the repository.

Rule 2897945: Reference deprecated shapes in comments only when they are still observable in the running system
src/Capacitor.App/ViewModels/HomeViewModel.cs[385-393]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Remove the unused compatibility overload and its historical `Back-compat` comment, or document a concrete currently supported producer if one exists.

## Issue Context
No repository callers use the `NoticeFor(LaunchAvailability, bool)` overload, and the comment identifies no persisted data, configuration, or supported client that requires it.

## Fix Focus Areas
- src/Capacitor.App/ViewModels/HomeViewModel.cs[385-393]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Comment cites external spec coordinate ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
The modified OutcomeBrushConverter comment references spec §7, making its meaning depend on
external process metadata. Comments must describe current behavior without design/spec coordinates.
Code

src/Capacitor.App/Views/Converters.cs[20]

+/// Activity row outcome badge (spec §7): the same Connected/Disrupted greens and reds as the
Relevance

●●● Strong

Recent accepted findings removed process and specification metadata from code comments.

PR-#703
PR-#666

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Rule 2897915 prohibits design/spec coordinates such as section markers in modified comments. The
changed comment explicitly includes spec §7.

Rule 2897915: Avoid time-sensitive or process-reference metadata in code comments
src/Capacitor.App/Views/Converters.cs[20-23]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Remove the `spec §7` coordinate from the comment while retaining its current behavioral rationale.

## Issue Context
Comments must remain understandable without external design or process artifacts.

## Fix Focus Areas
- src/Capacitor.App/Views/Converters.cs[20-23]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. Repository failures become unobserved ✓ Resolved 🐞 Bug ☼ Reliability
Description
The repository-row callback discards SelectRepositoryAsync, so state-loading failures detach from
the UI event and the selection or harness restoration silently fails as an unobserved task. The
replaced click handler awaited this operation.
Code

src/Capacitor.App/Views/LauncherPaneView.axaml.cs[R111-113]

+        return ChoiceButton(grid, () => {
+            flyout.Hide();
+            _ = vm.SelectRepositoryAsync(repoPath);
Relevance

●●● Strong

The team accepted fixes for abandoned asynchronous work and unobserved teardown tasks in desktop
application code.

PR-#446
PR-#740

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The new row callback explicitly discards the task. SelectRepositoryAsync awaits _state.LoadAsync
without catching failures, so an I/O or parsing exception propagates into the detached task rather
than an awaited event path.

src/Capacitor.App/Views/LauncherPaneView.axaml.cs[110-114]
src/Capacitor.App/ViewModels/HomeViewModel.cs[490-496]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Ensure asynchronous repository selection is awaited and failures are handled through the application's UI error path rather than becoming unobserved tasks.

## Issue Context
The new generic choice callback is synchronous, although repository selection loads persisted state asynchronously. Adapt the callback abstraction to support asynchronous operations and retain flyout-close behavior.

## Fix Focus Areas
- src/Capacitor.App/Views/LauncherPaneView.axaml.cs[110-114]
- src/Capacitor.App/ViewModels/HomeViewModel.cs[490-496]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View medium (4)
5. Repair outcomes lose visibility ✓ Resolved 🐞 Bug ◔ Observability
Description
PresentOutcomeAsync now logs unmapped Attention outcomes without displaying them, but
AttentionCopyFor omits the production tokens running_without_daemon_pid and
daemon_running_outside_service. Those service-ownership failures therefore leave users without the
recovery banner or actionable diagnosis previously shown.
Code

src/Capacitor.App/App.axaml.cs[R1003-1005]

+                    // Opaque tokens are for the log — a bare "needs attention (token)" banner helps nobody.
+                    Console.Error.WriteLine($"kcap: daemon mutation needs attention ({named}) — not shown in the UI");
+                }
Relevance

●●● Strong

Accepted visibility-loss findings closely match prior accepted recovery and actionable-error
feedback.

PR-#608
PR-#446

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The mutation lane emits both omitted tokens as AttentionRepair, and classification routes every
such outcome to RecoverySurface.Attention. The new fallback skips surface.Attention whenever
AttentionCopyFor returns null, which it does for both tokens.

src/Capacitor.App/Services/Mutation/DaemonMutationLane.cs[308-309]
src/Capacitor.App/Services/Mutation/DaemonMutationLane.cs[343-349]
src/Capacitor.App/App.axaml.cs[998-1005]
src/Capacitor.App/App.axaml.cs[1023-1049]
src/Capacitor.App/App.axaml.cs[1055-1060]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Restore user-visible recovery messages for all production-generated daemon ownership repair outcomes.

## Issue Context
`AttentionRepair` always routes to the Attention surface, but the new token-to-copy mapping does not cover two tokens emitted by the mutation lane. Add actionable mappings and preferably enforce mapping coverage with tests so future production tokens cannot silently become log-only.

## Fix Focus Areas
- src/Capacitor.App/App.axaml.cs[998-1005]
- src/Capacitor.App/App.axaml.cs[1021-1049]
- src/Capacitor.App/Services/Mutation/DaemonMutationLane.cs[343-349]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Recovery subscriptions accumulate ✗ Dismissed 🐞 Bug ➹ Performance
Description
Each rebuilt MainWindowViewModel calls HomeViewModel.AttachDaemonRecovery, which adds another
set of long-lived subscriptions retained until application shutdown. Since real window close
discards the window without disposing its view model, repeated close/reopen cycles retain old
recovery graphs and perform duplicate status processing.
Code

src/Capacitor.App/ViewModels/MainWindowViewModel.cs[R304-307]

+        // Launcher banner owns the chrome; share the same Start/Reconnect commands and start-message
+        // lane so the pane never drifts from what MainWindow already drives.
+        home?.AttachDaemonRecovery(
+            StartDaemonCommand, RetryCommand, canStart, canRetry, _startMessageChanges);
Relevance

●● Moderate

Subscription lifetime concerns are credible, but historical evidence is indirect and window
ownership conventions remain uncertain.

PR-#740

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The new attachment subscribes Home to observables owned by each main-window view model, and Home
retains every OAPH/subscription in its application-lifetime composite. The coordinator discards a
closed window and later constructs another, but MainWindowViewModel is not disposable and no close
path removes the prior attachment.

src/Capacitor.App/ViewModels/MainWindowViewModel.cs[27-27]
src/Capacitor.App/ViewModels/MainWindowViewModel.cs[277-307]
src/Capacitor.App/ViewModels/HomeViewModel.cs[317-341]
src/Capacitor.App/Services/MainWindowCoordinator.cs[29-43]
src/Capacitor.App/App.axaml.cs[1273-1300]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Give each main-window recovery attachment an explicit lifetime so closing or rebuilding the window removes subscriptions associated with the old view model.

## Issue Context
`AttachDaemonRecovery` stores every generated subscription in Home's application-lifetime composite, while the main-window coordinator can repeatedly create new view models. Return a disposable attachment, replace the previous attachment atomically, or make `MainWindowViewModel` disposable and invoke disposal on real close.

## Fix Focus Areas
- src/Capacitor.App/ViewModels/MainWindowViewModel.cs[277-307]
- src/Capacitor.App/ViewModels/HomeViewModel.cs[317-341]
- src/Capacitor.App/Services/MainWindowCoordinator.cs[29-43]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


7. Reconnect status never resolves ✓ Resolved 🐞 Bug ☼ Reliability
Description
When Start daemon finds an already-running service, it publishes a permanent “Reconnecting…” status
and fire-and-forgets the attach retry. If that retry returns to Unreachable, the UI only replaces
the exact ReconnectingMessage value, so the banner continues to claim it is reconnecting until a
successful connection occurs.
Code

src/Capacitor.App/Services/DaemonLifecycleController.cs[R666-667]

+                    _surface.Status("Daemon service is already running. Reconnecting…");
                    _ = _client.RestartLoopAsync();
Relevance

●● Moderate

The stale reconnect state is plausible, but no closely matching historical precedent establishes
team treatment.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The changed branch emits a different reconnect-in-progress string and does not await or observe
RestartLoopAsync. The view model clears messages only after Connected, and its Unreachable handler
replaces only ReconnectingMessage, not the lifecycle branch's new text.

src/Capacitor.App/Services/DaemonLifecycleController.cs[665-668]
src/Capacitor.App/ViewModels/MainWindowViewModel.cs[363-374]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The already-running daemon branch reports an in-progress reconnect, but does not provide failure feedback when the fire-and-forget reattach attempt fails. Ensure this status is replaced with actionable failure copy when attachment remains unreachable.

## Issue Context
`MainWindowViewModel` clears start messages only on Connected and only recognizes its own `ReconnectingMessage` sentinel when converting an unreachable retry into failure copy. The lifecycle's different message therefore remains indefinitely after a failed reconnect.

## Fix Focus Areas
- src/Capacitor.App/Services/DaemonLifecycleController.cs[665-668]
- src/Capacitor.App/ViewModels/MainWindowViewModel.cs[363-374]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


8. Header drag strip shrinks ✓ Resolved 🐞 Bug ≡ Correctness
Description
The WorkContext header’s pointer handler now belongs only to the label rather than its full-width
container. Clicking empty header space no longer initiates window dragging, while the prior
DockPanel handler covered the entire header.
Code

src/Capacitor.App/Views/WorkContextView.axaml[R98-100]

+                <Grid ColumnDefinitions="*,Auto" MinHeight="30">
+                    <TextBlock Grid.Column="0" Text="ABOUT THIS WORK" Classes="eyebrow" Background="Transparent"
+                               VerticalAlignment="Center" PointerPressed="OnHeaderPointerPressed" />
Relevance

●● Moderate

The interaction regression is deterministic, but available rejection precedents concern different UI
behavior and are not decisive.

PR-#666

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The new Grid has no pointer handler, whereas its TextBlock alone has PointerPressed. The handler
is designed to reject button-originated events and otherwise call WindowChrome.BeginDrag, so empty
Grid area has no equivalent route to start dragging.

src/Capacitor.App/Views/WorkContextView.axaml[97-113]
src/Capacitor.App/Views/WorkContextView.axaml.cs[15-20]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The WorkContext header should remain a full-width window drag target except for interactive controls. The handler was moved from the surrounding header container onto the text label, leaving blank header chrome non-draggable.

## Issue Context
The existing handler already excludes Button descendants before calling `WindowChrome.BeginDrag`, so it is safe to attach it to the header Grid.

## Fix Focus Areas
- src/Capacitor.App/Views/WorkContextView.axaml[98-100]
- src/Capacitor.App/Views/WorkContextView.axaml.cs[15-20]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
✅ Compliance rules (platform): 56 rules
Review mode: 🧠 Deep: This broad desktop UX change spans 52 files and 185 hunks across launcher, authentication/reauth, daemon recovery, chat tooling, workspace navigation, styling, and tests, creating many independent paths where subtle regressions are easy to miss.

Grey Divider

Tip of the day
💡 Did you know, you can keep summaries lean with Finding overflow, which tucks the rest behind 'View more'

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread src/Capacitor.App/Views/Converters.cs Outdated
Comment thread src/Capacitor.App/ViewModels/HomeViewModel.cs Outdated
Comment thread src/Capacitor.App/ViewModels/HomeViewModel.cs
Comment thread src/Capacitor.App/Views/LauncherPaneView.axaml.cs Outdated
Comment thread src/Capacitor.App/App.axaml.cs
Comment thread src/Capacitor.App/ViewModels/MainWindowViewModel.cs
Comment thread src/Capacitor.App/Services/DaemonLifecycleController.cs Outdated
Comment thread src/Capacitor.App/Views/WorkContextView.axaml Outdated
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.

2 participants