Skip to content

Add desktop daemon settings - #886

Merged
alexeyzimarev merged 3 commits into
mainfrom
alexeyzimarev/ai-2535-desktop-settings-ui
Sep 11, 2026
Merged

alexeyzimarev merged 3 commits into
mainfrom
alexeyzimarev/ai-2535-desktop-settings-ui

Conversation

@alexeyzimarev

@alexeyzimarev alexeyzimarev commented Sep 11, 2026 •

Copy link
Copy Markdown
Member

Closes #791 — AI-2535

What & why

Settings opens from the application menu (⌘,) and tray. Capacity saves to the selected profile before applying live, with explicit feedback for stopped or older daemons. Rename requires an idle daemon, a free name and confirmation, then replaces the service and relaunches the app.

Where to look

Rename waits for startup, checks CLI retire support before saving, and rejects environment-controlled names. After any transaction outcome, the old app requires restart before managing the daemon. Transaction failures keep the new name and show recovery; a pre-spawn unsupported-CLI refusal restores it. Unbundled builds require an app restart.

Verification

Claude review clean at 3a3d9c1. 1,729 desktop tests passed; full app/test rebuild has zero warnings. macOS app and CLI Release publishes succeeded; no CLI AOT/trimming diagnostics (local Homebrew deployment-target linker warnings remain). Native preview checked layout, command gates and capacity feedback with isolated configuration and fake daemon data.

@linear-code

linear-code Bot commented Sep 11, 2026

Copy link
Copy Markdown

AI-2535

@alexeyzimarev
alexeyzimarev marked this pull request as ready for review September 11, 2026 11:05
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 11, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-11T11:11:25.554932Z 3a3d9c1 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Add desktop daemon settings and safe rename workflow

✨ Enhancement 🧪 Tests 📝 Documentation 🕐 40+ Minutes

Grey Divider

AI Description

• Adds desktop Settings access for profile-scoped daemon capacity and name management.
• Persists capacity before live application, with offline and compatibility feedback.
• Safely retires renamed services and blocks stale lifecycle actions until restart.
Diagram

graph TD
  Entry["App Menu / Tray"] --> Window["Settings Window"] --> VM["Settings ViewModel"]
  VM --> Store["Profile Store"] --> Config[("Profile Config")]
  VM --> IPC["Daemon Settings IPC"]
  VM --> Lane["Mutation Lane"] --> CLI["CLI Replace"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Defer rename until next app startup
  • ➕ Reduces the live Settings workflow and relaunch coordination.
  • ➕ Avoids managing a long-running service transaction from the current process.
  • ➖ Leaves the old service installed until restart.
  • ➖ Provides weaker immediate confirmation and can allow competing daemon identities.
2. Introduce a dedicated rename coordinator
  • ➕ Moves the multi-step rename transaction out of the view model.
  • ➕ Creates a reusable boundary for preflight, persistence, mutation, and recovery.
  • ➖ Adds another orchestration layer around the existing mutation lane.
  • ➖ Requires more lifecycle ownership and disposal wiring for one workflow.

Recommendation: The current approach is appropriate: profile writes use the existing atomic mutation API, capacity uses the established local IPC capability, and service replacement stays inside the serialized mutation lane. Deferring rename weakens identity guarantees, while a dedicated coordinator would improve separation but adds substantial machinery without changing the transaction semantics; it can be considered later if more settings transactions are introduced.

Files changed (29) +1087 / -46

Enhancement (16) +500 / -32
App.axaml.csCompose and manage the Settings workflow +59/-8

Compose and manage the Settings workflow

• Adds application-menu and tray entry points, creates a singleton Settings window, and wires profile storage, daemon IPC, mutation-lane rename, confirmation, and relaunch dependencies. It also extends shutdown quiescence and closes Settings during app shutdown.

src/Capacitor.App/App.axaml.cs

ILifecycleSurface.csAdd rename confirmation prompt kind +1/-0

Add rename confirmation prompt kind

• Introduces a dedicated lifecycle prompt identifier for daemon rename confirmation.

src/Capacitor.App/Services/ILifecycleSurface.cs

KcapCli.csSupport verified service retirement during replacement +25/-11

Support verified service retirement during replacement

• Adds CLI capability probing for the retire flag and forwards the old service ID during replacement. Rename transactions receive a longer timeout and fail closed when the selected CLI cannot retire services.

src/Capacitor.App/Services/KcapCli.cs

DaemonMutationLane.csSerialize rename retirement and invalidate stale service identities +31/-5

Serialize rename retirement and invalidate stale service identities

• Adds retire capability preflight, forwards retirement targets, and tracks service IDs that may have been retired. Queued and future mutations against those identities are refused until app restart, except when an unsupported CLI prevented transaction spawn.

src/Capacitor.App/Services/Mutation/DaemonMutationLane.cs

MutationModel.csCarry retirement targets in mutation requests +2/-2

Carry retirement targets in mutation requests

• Extends mutation requests with an optional old service ID used by replacement transactions.

src/Capacitor.App/Services/Mutation/MutationModel.cs

MutationRequestFactory.csValidate daemon retirement requests +10/-2

Validate daemon retirement requests

• Allows replacement requests to include a sanitized retirement target while rejecting missing, identical, or non-replacement targets.

src/Capacitor.App/Services/Mutation/MutationRequestFactory.cs

WizardLateBinding.csForward retire operations through late-bound CLI +4/-2

Forward retire operations through late-bound CLI

• Updates the onboarding CLI adapter to expose retire capability checks and retirement-aware service installation.

src/Capacitor.App/Services/Onboarding/WizardLateBinding.cs

SettingsProfileStore.csAdd graph-pinned profile settings persistence +49/-0

Add graph-pinned profile settings persistence

• Introduces a store that edits only the profile and server attached to the app's daemon graph. It preserves concurrent configuration changes and conditionally restores a name after a pre-spawn rename refusal.

src/Capacitor.App/Services/SettingsProfileStore.cs

SettingsRenameMessage.csProvide actionable rename recovery messages +29/-0

Provide actionable rename recovery messages

• Maps rename mutation failures to user-facing explanations, restart guidance, and an explicit old-service uninstall recovery command.

src/Capacitor.App/Services/SettingsRenameMessage.cs

LifecyclePromptViewModel.csPresent daemon rename confirmations +2/-0

Present daemon rename confirmations

• Adds rename-specific dialog title and confirmation button text.

src/Capacitor.App/ViewModels/LifecyclePromptViewModel.cs

SettingsViewModel.csImplement daemon Settings behavior +221/-0

Implement daemon Settings behavior

• Adds validation, status rendering, command gates, persist-before-live capacity updates, and detailed degraded-result feedback. The rename workflow checks collision, confirmation, startup, idleness, and CLI support before saving, replacing the service, and relaunching or showing recovery guidance.

src/Capacitor.App/ViewModels/SettingsViewModel.cs

TrayViewModel.csExpose the Settings tray command +4/-1

Expose the Settings tray command

• Adds an enabled Settings command when application composition supplies an open-settings callback.

src/Capacitor.App/ViewModels/TrayViewModel.cs

AppMenuBar.csAdd Settings to the application menu +5/-1

Add Settings to the application menu

• Adds an optionally enabled Settings item with the macOS Command-comma keyboard shortcut.

src/Capacitor.App/Views/AppMenuBar.cs

SettingsWindow.axamlCreate the daemon Settings window +50/-0

Create the daemon Settings window

• Adds a fixed-size Avalonia settings form for daemon status, validated name editing, capacity editing, command controls, and outcome feedback.

src/Capacitor.App/Views/SettingsWindow.axaml

SettingsWindow.axaml.csInitialize the Settings window +7/-0

Initialize the Settings window

• Adds the code-behind required to load the new Avalonia Settings view.

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

TrayMenuBuilder.csAdd Settings to the tray menu +1/-0

Add Settings to the tray menu

• Places the Settings command immediately after the main-window action in the tray menu.

src/Capacitor.App/Views/TrayMenuBuilder.cs

Bug fix (1) +22 / -4
DaemonLifecycleController.csBlock lifecycle actions after daemon rename +22/-4

Block lifecycle actions after daemon rename

• Adds a restart-required guard before and after status queries, prompts, and lane mutations so the stale daemon graph cannot perform further lifecycle actions. It also maps the retire refusal exit code.

src/Capacitor.App/Services/DaemonLifecycleController.cs

Tests (9) +535 / -9
AppMenuBarTests.csTest Settings application-menu integration +18/-2

Test Settings application-menu integration

• Updates menu layout expectations and verifies Settings enablement, invocation, and Command-comma gesture wiring.

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

DaemonLifecycleControllerTests.csTest lifecycle refusal after rename +32/-3

Test lifecycle refusal after rename

• Covers restart-required guards before status lookup, during lookup, and after mutation execution. Test CLI doubles are extended for retirement capabilities and targets.

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

DaemonMutationLaneTests.csTest retirement safety in the mutation lane +82/-0

Test retirement safety in the mutation lane

• Verifies stale queued and future actions are refused after confirmed or uncertain renames, while pre-spawn unsupported-CLI failures preserve the old graph. Also covers capability preflight, target dispatch, and refusal-reason classification.

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

KcapCliTests.csTest CLI retirement arguments and compatibility gates +28/-0

Test CLI retirement arguments and compatibility gates

• Verifies retire argument forwarding, the extended rename timeout, unsupported CLI refusal, and rejection of retirement without replacement.

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

MutationRequestFactoryTests.csTest invalid retirement request rejection +9/-0

Test invalid retirement request rejection

• Covers retirement targets used with the wrong verb or resolving to the replacement service identity.

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

ScriptedLocalControlOps.csExpose capacity update start in the IPC test double +2/-0

Expose capacity update start in the IPC test double

• Adds a callback allowing tests to observe when a live daemon settings request begins.

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

SettingsViewModelTests.csCover capacity and rename Settings workflows +291/-0

Cover capacity and rename Settings workflows

• Adds broad coverage for validation, profile isolation, persist-before-apply ordering, degraded capacity outcomes, rename gates, concurrent edits, recovery, retirement requests, and relaunch behavior.

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

SettingsWindowSmokeTests.csSmoke-test Settings bindings and layout +53/-0

Smoke-test Settings bindings and layout

• Verifies initial values, status text, two-way editing, command enablement, idle-state transitions, and basic rendered dimensions.

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

TrayAdapterTests.csTest Settings tray placement and invocation +20/-4

Test Settings tray placement and invocation

• Updates tray item counts and ordering, then verifies the Settings item follows the main-window action and invokes its command.

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

Documentation (3) +30 / -1
README.mdDocument desktop daemon settings behavior +2/-0

Document desktop daemon settings behavior

• Explains how to open Settings, when capacity applies, and the requirements and recovery behavior for daemon rename. Documents app restart, CLI compatibility, and environment override constraints.

README.md

CHANGES.mdRecord settings persistence and mutation-lane invariants +18/-0

Record settings persistence and mutation-lane invariants

• Documents profile pinning, persist-before-apply capacity behavior, rename preflight, service retirement, and post-transaction restart requirements.

docs/CHANGES.md

2026-09-10-ai2535-desktop-daemon-settings-design.mdHarden the daemon rename design +10/-1

Harden the daemon rename design

• Adds startup and environment gates, CLI retire preflight, conditional name restoration, and stale lifecycle-action refusal after rename outcomes.

docs/superpowers/specs/2026-09-10-ai2535-desktop-daemon-settings-design.md

@qodo-code-review

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

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (1) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Daemon renaming is always unavailable 🐞 Bug ≡ Correctness
Description
KcapCli.SupportsServiceRetireAsync runs kcap daemon --help --no-update-check and requires both
exit code zero and --retire in its output. DaemonCommands.HandleAsync interprets --help as an
unknown daemon subcommand, while the only usage text containing --retire belongs to the nested
daemon service command, so CanRetireAsync returns false and RenameAsync refuses every rename
before saving the name or entering the mutation lane.
Code

src/Capacitor.App/Services/KcapCli.cs[R140-143]

+        var help = await Run(cliPath, ["daemon", "--help", "--no-update-check"],
+            new RunOptions(EnvOverlay: Env(), Timeout: VersionTimeout), ct).ConfigureAwait(false);
+        return !help.TimedOut && help.ExitCode == 0 &&
+            (help.Stdout.Contains("--retire", StringComparison.Ordinal) || help.Stderr.Contains("--retire", StringComparison.Ordinal));
Relevance

●●● Strong

Wrong help command makes the retire capability probe fail deterministically, blocking every rename.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The added probe asks the wrong command level for the feature. The CLI dispatcher handles the
supplied --help token as a daemon subcommand rather than routing to service help, and the nested
service usage is where the retire flag is actually advertised.

src/Capacitor.App/Services/KcapCli.cs[137-144]
src/Capacitor.Cli/Commands/DaemonCommands.cs[19-41]
src/Capacitor.Cli/Commands/DaemonServiceCommands.cs[659-665]

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

## Issue description
`SupportsServiceRetireAsync` probes the top-level `daemon` command, whose help output does not expose the service-install `--retire` option and exits unsuccessfully. As a result, every supported CLI is classified as unsupported and Settings never permits a daemon rename.

## Fix Focus Areas
- src/Capacitor.App/Services/KcapCli.cs[137-144]
- src/Capacitor.Cli/Commands/DaemonCommands.cs[19-41]
- src/Capacitor.Cli/Commands/DaemonServiceCommands.cs[659-665]

## Recommended Fix
Probe the `daemon service` command's usage/capability surface instead of top-level `daemon`, and evaluate its documented help behavior correctly rather than requiring a zero exit code from a usage path that intentionally returns nonzero. Alternatively, add a dedicated zero-exit CLI capability query for service retirement and make the app call that query; retain the requirement that the returned output explicitly proves `--retire` support.

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


2. Renames proceed after agents become active 🐞 Bug ≡ Correctness
Description
RenameAsync checks Idle before awaiting SaveNameAsync, then invokes _runMutation without
checking the asynchronously updated status or snapshot again. If an agent starts while the profile
write is in progress, the retire transaction has no active-agent gate and can replace the old
service despite the rename requirement for zero active agents.
Code

src/Capacitor.App/ViewModels/SettingsViewModel.cs[R185-187]

+            var previous = await _settings.SaveNameAsync(name, _lifetime.Token);
+            Message = "Name saved. Restarting the daemon…";
+            var outcome = await _runMutation(request!, _lifetime.Token);
Relevance

●●● Strong

Recent history accepts rechecks preventing stale asynchronous state from overwriting newer user or
daemon changes.

PR-#766

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The view model's last idle check precedes an awaited configuration write, while status and snapshot
subscriptions can update Idle during that await. The CLI retirement implementation checks service
ownership and target collision but does not check the daemon's active-agent count before retiring
the old unit.

src/Capacitor.App/ViewModels/SettingsViewModel.cs[167-187]
src/Capacitor.App/ViewModels/SettingsViewModel.cs[102-103]
src/Capacitor.Cli/Services/ServiceVerify.cs[785-805]

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 rename flow can pass its idle check, yield while saving the profile, and then retire the old service after an agent has become active. The CLI retirement path does not independently enforce the active-agent requirement.

## Fix Focus Areas
- src/Capacitor.App/ViewModels/SettingsViewModel.cs[181-190]
- src/Capacitor.Cli/Services/ServiceVerify.cs[785-805]

## Recommended Fix
Make the zero-active-agents condition part of the final rename transaction boundary. At minimum, recheck fresh idle evidence after `SaveNameAsync` and conditionally restore the name when the daemon became busy; preferably also make the retire operation refuse atomically when the old daemon has active agents so an agent cannot start between the final UI check and retirement.

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



Remediation recommended

3. Capacity saves can race daemon changes 📘 Rule violation ⌂ Architecture
Description
SaveAsync calls _ops.PutDaemonSettingsAsync directly rather than submitting the live capacity
mutation through the shared DaemonMutationLane. When a save overlaps a queued install, replace,
start, or retirement action, this write runs outside the lane's ordering and retirement guards
against the changing daemon graph.
Code

src/Capacitor.App/ViewModels/SettingsViewModel.cs[141]

+                    var ack = await _ops.PutDaemonSettingsAsync(new DaemonSettingsPutDto(capacity), _lifetime.Token);
Relevance

●● Moderate

A close lane-bypass precedent was rejected, but this rule explicitly covers all desktop daemon
writes.

PR-#770

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 2738493 requires every desktop daemon write, including protocol mutations, to use
the single shared mutation lane. The added live-save branch directly invokes the local control write
operation instead.

Rule 2738493: Route all desktop daemon mutations through the single DaemonMutationLane abstraction
src/Capacitor.App/ViewModels/SettingsViewModel.cs[133-146]

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

## Issue description
Live capacity updates bypass the shared daemon mutation lane, allowing them to run independently of lifecycle mutations and the lane's retirement guards.

## Fix Focus Areas
- src/Capacitor.App/ViewModels/SettingsViewModel.cs[133-146]

## Recommended Fix
Add a capacity-update operation to the app-lifetime daemon mutation lane and inject that operation into `SettingsViewModel`. Replace the direct `_ops.PutDaemonSettingsAsync` call with the lane-backed operation while preserving the existing acknowledgement and error messages.

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


Grey Divider

Context sources
✅ Compliance rules (platform): 64 rules
✅ Cross-repo context — repo relationships
Review mode: 🧠 Deep: This is a broad, bug-dense desktop settings feature spanning UI, persistence, lifecycle mutation, CLI compatibility, rename transactions, relaunch behavior, and many independent code paths with high blast radius.

Grey Divider

Tip of the day
💡 Did you know, you can switch off images and animations for a plain-text comment

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Message = "Saved. Update the daemon to apply capacity changes without a restart.";
} else {
try {
var ack = await _ops.PutDaemonSettingsAsync(new DaemonSettingsPutDto(capacity), _lifetime.Token);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

3. Capacity saves can race daemon changes 📘 Rule violation ⌂ Architecture

SaveAsync calls _ops.PutDaemonSettingsAsync directly rather than submitting the live capacity
mutation through the shared DaemonMutationLane. When a save overlaps a queued install, replace,
start, or retirement action, this write runs outside the lane's ordering and retirement guards
against the changing daemon graph.
Agent Prompt
## Issue description
Live capacity updates bypass the shared daemon mutation lane, allowing them to run independently of lifecycle mutations and the lane's retirement guards.

## Fix Focus Areas
- src/Capacitor.App/ViewModels/SettingsViewModel.cs[133-146]

## Recommended Fix
Add a capacity-update operation to the app-lifetime daemon mutation lane and inject that operation into `SettingsViewModel`. Replace the direct `_ops.PutDaemonSettingsAsync` call with the lane-backed operation while preserving the existing acknowledgement and error messages.

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

Comment on lines +185 to +187
var previous = await _settings.SaveNameAsync(name, _lifetime.Token);
Message = "Name saved. Restarting the daemon…";
var outcome = await _runMutation(request!, _lifetime.Token);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. Renames proceed after agents become active 🐞 Bug ≡ Correctness

RenameAsync checks Idle before awaiting SaveNameAsync, then invokes _runMutation without
checking the asynchronously updated status or snapshot again. If an agent starts while the profile
write is in progress, the retire transaction has no active-agent gate and can replace the old
service despite the rename requirement for zero active agents.
Agent Prompt
## Issue description
The rename flow can pass its idle check, yield while saving the profile, and then retire the old service after an agent has become active. The CLI retirement path does not independently enforce the active-agent requirement.

## Fix Focus Areas
- src/Capacitor.App/ViewModels/SettingsViewModel.cs[181-190]
- src/Capacitor.Cli/Services/ServiceVerify.cs[785-805]

## Recommended Fix
Make the zero-active-agents condition part of the final rename transaction boundary. At minimum, recheck fresh idle evidence after `SaveNameAsync` and conditionally restore the name when the daemon became busy; preferably also make the retire operation refuse atomically when the old daemon has active agents so an agent cannot start between the final UI check and retirement.

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

Comment on lines +140 to +143
var help = await Run(cliPath, ["daemon", "--help", "--no-update-check"],
new RunOptions(EnvOverlay: Env(), Timeout: VersionTimeout), ct).ConfigureAwait(false);
return !help.TimedOut && help.ExitCode == 0 &&
(help.Stdout.Contains("--retire", StringComparison.Ordinal) || help.Stderr.Contains("--retire", StringComparison.Ordinal));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

2. Daemon renaming is always unavailable 🐞 Bug ≡ Correctness

KcapCli.SupportsServiceRetireAsync runs kcap daemon --help --no-update-check and requires both
exit code zero and --retire in its output. DaemonCommands.HandleAsync interprets --help as an
unknown daemon subcommand, while the only usage text containing --retire belongs to the nested
daemon service command, so CanRetireAsync returns false and RenameAsync refuses every rename
before saving the name or entering the mutation lane.
Agent Prompt
## Issue description
`SupportsServiceRetireAsync` probes the top-level `daemon` command, whose help output does not expose the service-install `--retire` option and exits unsuccessfully. As a result, every supported CLI is classified as unsupported and Settings never permits a daemon rename.

## Fix Focus Areas
- src/Capacitor.App/Services/KcapCli.cs[137-144]
- src/Capacitor.Cli/Commands/DaemonCommands.cs[19-41]
- src/Capacitor.Cli/Commands/DaemonServiceCommands.cs[659-665]

## Recommended Fix
Probe the `daemon service` command's usage/capability surface instead of top-level `daemon`, and evaluate its documented help behavior correctly rather than requiring a zero exit code from a usage path that intentionally returns nonzero. Alternatively, add a dedicated zero-exit CLI capability query for service retirement and make the app call that query; retain the requirement that the returned output explicitly proves `--retire` support.

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3a3d9c16f8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

IsBusy = true;
Message = null;
try {
if (await _targetRunning(name, _lifetime.Token)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Reject names belonging to stopped services

When the target name belongs to a stopped-but-installed daemon, this socket probe returns false and the rename proceeds. The resulting --replace --verify --retire request reaches ServiceVerify.ApplyReplaceMatrixAsync, where the pre.UnitPresent branch clears the target unit without verifying its profile (src/Capacitor.Cli/Services/ServiceVerify.cs:1081-1084). Renaming one daemon to the name of another profile's stopped service therefore silently removes that other background service; check installed-unit ownership or refuse any occupied target name before dispatching the rename.

Useful? React with 👍 / 👎.

Comment on lines +181 to +182
if (!_startupSettled.IsCompletedSuccessfully || !Idle) {
Message = "Wait until startup has finished and the daemon is idle before renaming.";

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Fence new launches before retiring the daemon

If a remote launch is admitted after this final Idle check but before the queued CLI mutation retires the old service, the rename proceeds even though an agent is now active. The mutation lane serializes service mutations, not agent launches, and ServiceVerify.RetireAsync clears the service and waits for it to stop without checking the active-agent count (src/Capacitor.Cli/Services/ServiceVerify.cs:1035-1038), so this race can terminate newly started agent work despite the UI promising rename is restricted to an idle daemon. Establish an admission/pause fence that remains held through retirement, or enforce idle atomically in the daemon-side transaction.

Useful? React with 👍 / 👎.

@alexeyzimarev
alexeyzimarev merged commit 153e1f0 into main Sep 11, 2026
7 checks passed
@alexeyzimarev
alexeyzimarev deleted the alexeyzimarev/ai-2535-desktop-settings-ui branch September 11, 2026 11:27
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.

Extend desktop app settings to configure the daemon

1 participant