Skip to content

feat(desktop): real-use Desktop product path (D1-D6 complete on Windows) - #37

Open
AllureCurtain wants to merge 7 commits into
mainfrom
feature/desktop-real-use-final
Open

feat(desktop): real-use Desktop product path (D1-D6 complete on Windows)#37
AllureCurtain wants to merge 7 commits into
mainfrom
feature/desktop-real-use-final

Conversation

@AllureCurtain

@AllureCurtain AllureCurtain commented Aug 25, 2026

Copy link
Copy Markdown
Owner

Summary

Delivers the D package of docs/plans/2026-08-18-tui-desktop-real-use-final-implementation.md: the Windows Desktop product path, from install to a real Agent task equivalent to the TUI's.

Desktop stays a thin Tauri host over the shared rove-api, Runtime, ProductStore, Tool Registry, provider catalog, canonical events, and durable run state. No Agent loop, no Desktop-private event protocol, no unilateral change to the Core Agent loop, Provider wire protocol, or Tool Registry permissions.

D1-D6 are complete on Windows. The final section 10.1 A gate is still outstanding and must run on merged main.

What's in the code

  • Windows provider_credential_prompt: accepts only non-secret profile metadata, opens the native credential UI with CREDUI_FLAGS_DO_NOT_PERSIST, hands the raw credential straight to the shared onboarding service. The secret never reaches WebView state, ordinary config, logs, or traces.
  • Settings create/test/use flow driving the shared ProviderOnboardingService, so a Start-menu launch can configure and enable a provider with no terminal and no TOML.
  • Native directory picker creating a correct Product Workspace.
  • Bearer-authenticated SSE inside the WebView, reconnecting only the focused job, with no duplicate submission on an ambiguous job-start response.
  • Negative tests pinning secret-free projection: secure_onboarding_projects_catalog_identity_without_serializing_the_secret, probe_and_use_metadata_are_bounded_and_secret_free.

D6 installed-state gate: 9/9 pass

Run 2026-08-26 against the real SiliconFlow provideropenai, https://api.siliconflow.cn/v1, deepseek-ai/DeepSeek-V3.2 — with the key read only from the Windows keyring. No Fake provider was used anywhere in this gate, and no temporary PowerShell environment variable was involved. Desktop was launched from the Start-menu shortcut every time.

item result
install succeeds, launch needs no dev tooling pass
uninstall + reinstall round trip pass, 10/10
provider credentials resolve after Start-menu launch pass
two read-only turns on the real model, same as TUI pass
Chat/Inspector show real tool calls and their evidence pass
a modification turn: approval, change, test, diff pass
SSE disconnect/reconnect without duplicate submission pass, 5/5
restart restores workspace, sessions, terminal state pass, 10/10
reinstall + relaunch restores state pass, 6/6

Details worth pulling out:

  • Tool calls are genuinely native. 41 tool calls across 8 distinct tools, every one carrying a provider-side tool_use_id — not JSON embedded in assistant text. 6 approval events.
  • SSE replay is exact. Streamed 40 events, dropped the socket, reopened with after=40, resumed at exactly seq 41 and drained to 1148. No duplicate seqs, exactly one run_completed, no gaps, one run id per job.
  • Restart used a hard kill, including WebView2 children, which is a stronger test than a graceful window close. Workspace identity, the full session set with statuses, diff, artifact count and sha256 digests all came back. /jobs/{id}/state returns 404 — the job registry is ephemeral by design, so terminal state is recovered from the durable report (status: success, termination_reason: final).
  • Uninstall preserves user data. %APPDATA%\Rove held 146 files / 11204219 bytes at installed, uninstalled, and reinstalled states alike.
  • Both NSIS packages are perMachine. Install and uninstall must run as an elevated child; driving uninstall.exe from an unelevated session fails with WinError 740. The earlier claim that installation was impossible in a non-administrator session is now corrected in the docs.

Evidence package at C:\rove-evidence\d6-desktop\manifest.json indexes every artifact with a sha256 digest, alongside report.json, tool-events.jsonl, transcript.md, session-diff.json, uninstall-round-trip.{json,md}, provider-safe-identity.json, git-status.txt, checks.json. Generated, and deliberately not committed. Every file passed a leak scan (sk-, SILICONFLOW_API_KEY=, Bearer ey, api_key":") before being written.

Deterministic checks

cargo fmt --all --check                                  exit 0
cargo clippy --workspace --all-targets -- -D warnings    exit 0
cargo test --workspace                                   1567 passed / 0 failed
cargo test -p rove-api                                   137 passed
cargo test -p rove-desktop --all-targets                 13 lib + 3 integration passed
pnpm test        (apps/web)                              37 files / 255 tests passed
pnpm typecheck   (apps/web)                               exit 0
pnpm build:desktop                                        exit 0
pnpm dlx @tauri-apps/cli@2 build --bundles "msi,nsis" --ci  MSI + NSIS produced

CARGO_TARGET_DIR was redirected to C:\rove-build\desktop-real-use-final because the D: volume was short on space, so bundles landed there rather than in the in-repo target/release/bundle/. The docs previously stated the in-repo path unconditionally; that is now corrected.

Product defects found, not fixed

Confirmed by observation while running the gate, each recorded in the manifest. Left unfixed on purpose — section 6 forbids this branch from unilaterally changing Core Agent loop, Provider wire protocol, or Tool Registry permission behaviour, and none of these are Desktop-owned:

  1. needs_attention is a terminal deadlock. A run ending without a final answer strands the session; there is no recovery endpoint. error accepts new turns, needs_attention does not.
  2. Project config is never loaded on the API/Desktop path. project_config_loaded is hardcoded false even when the project_configuration trust capability has been granted.
  3. max_model_turns_per_step = 4 is unreachable from Desktop. Hardcoded as DEFAULT_MAX_MODEL_TURNS_PER_STEP in runtime/src/planning/execution.rs.
  4. The product UI cannot select an agent profile. POST /jobs honours an agent field, but CreateProductMessageRequest sets deny_unknown_fields, so the Desktop and Web product path cannot send one. Identical on main; this branch adds no agent-selection frontend code.

Test plan

  • Deterministic workspace gate (fmt, clippy, cargo test, web tests, typecheck, build)
  • D6 installed-state gate on real SiliconFlow, 9/9
  • Uninstall/reinstall round trip with user-data retention
  • SSE disconnect/reconnect replay contiguity
  • Restart recovery from durable state
  • pnpm test:e2e (Playwright) — not run here, part of the final A1 gate on main
  • Desktop screenshots for the D6 journey — not captured, recorded as a gap rather than filled with a synthetic image
  • Section 10.1 A gate — must run on final main after both branches merge; this Windows-only, single-machine evidence does not substitute for it, nor for the A3 installed-state TUI gate

Scope notes

Windows-only. No release claim is made for unverified platforms. No existing tests were deleted; new tests are limited to the §8.2 golden path plus the security regressions above.

…use-final

# Conflicts:
#	docs/runtime/implementation-status.md
Pre-existing clippy::drain_collect failure on origin/main blocked
cargo clippy --workspace --all-targets -- -D warnings, which the A1
deterministic gate requires. std::mem::take is semantically identical
for Vec<StreamEvent>: the source is left empty and the elements move
into the new binding without a second allocation.

Not Desktop-scope work; applied only to unblock the workspace gate.
Desktop D2 previously stopped at a safe keyring receipt boundary because
the shared onboarding contract was not yet on main. That contract landed
in cc9799f, so Desktop now consumes it instead of maintaining a private
credential path.

Shared-service integration:

- add apps/api/src/product/provider_onboarding.rs, an in-process facade
  over rove_app_bootstrap::ProviderOnboardingService that keeps keyring
  storage, real inventory probing, Catalog CAS publication, and failure
  compensation owned by the shared service;
- expose ApiState::onboard_product_provider / probe_product_provider /
  use_product_provider. The credential is a separate non-serializable
  &str argument, so it cannot become an HTTP or WebView payload. There
  is no HTTP route that accepts a provider secret;
- project the published profile into ProductStore as an identity stub
  only. A projection failure after a successful publication returns the
  typed provider_product_projection code and requests reconciliation
  rather than diverging from the shared Catalog.

Desktop host:

- the Tauri host holds the embedded ApiState and reuses it for the new
  provider_credential_prompt, provider_profile_probe, and
  provider_profile_use commands;
- the Windows native prompt collects the secret, sets
  CREDUI_FLAGS_DO_NOT_PERSIST so the dialog cannot persist credentials
  on its own, hands the value straight to the shared service, and
  zeroizes both the wide buffers and the decoded String on every path;
- remove the Desktop-private com.rove.agent.provider keyring receipt and
  drop the now-unused keyring dependency;
- no new Desktop event type, emit, or listener: canonical events remain
  the only projection source.

Web surface:

- desktop-commands.ts validates and normalizes profile id, label, API
  base, model, and revision, and rejects non-remote provider types and
  browser use before invoking;
- Settings splits by host. Desktop renders native onboarding, probe,
  Catalog publication, refresh, and selection with a SiliconFlow preset;
  the browser keeps the existing env/file/reference CRUD and never gets
  a secret path;
- add refreshProviderProfiles and typed keyring/reconciliation/
  model-unavailable error copy.

Verification (real exit codes):

  cargo fmt --all --check                                 0
  cargo clippy --workspace --all-targets -- -D warnings   0
  cargo test --workspace                                  0  (1567 passed, 0 failed)
  cargo test -p rove-api                                  0  (137)
  cargo test -p rove-desktop --all-targets                0  (13 lib + 3 integration)
  pnpm test                                               0  (37 files / 255 tests)
  pnpm typecheck                                          0
  pnpm build:desktop                                      0

Negative coverage asserts the secret never appears in a serialized
receipt, that failures are typed and redacted, and that probe/use
metadata stays bounded and secret-free.

D6 is NOT met. Installation, Start menu launch, the credentialed
SiliconFlow two-turn run, and restart restoration remain unverified: the
NSIS package is perMachine and installation needs UAC, which this
session did not have. The implementation plan stays Partially
Implemented and no document claims Desktop real-use completion.
Update Desktop status to match the code now on this branch, without
overclaiming.

- desktop-real-use.md: the Shared Dependency section is resolved (cc9799f
  is contained in origin/main at 8a4e141, which this branch merged), the
  contract section describes the in-process facade and the Desktop/browser
  Settings split, and the verified-checks block records real exit codes
  including the deterministic A1 gate;
- split Open Gates into what closed on this branch and what still blocks a
  real-use claim, and state the UAC/perMachine reason installation was not
  run;
- implementation-status.md, acceptance-matrix.md, release-readiness.md:
  replace the "waiting for the shared contract" wording with the integrated
  state plus the named test evidence, and keep installation, the
  credentialed SiliconFlow run, restart restoration, and D6 unverified;
- implementation plan: mark the D6 items that deterministic evidence
  supports, keep every installed-state item unchecked, and record the
  blocking reason. Status stays Partially Implemented;
- README: document the Desktop native provider onboarding path and point
  at the unverified-installation caveat.

Playwright pnpm test:e2e was not run on this branch and remains part of
the final A1 gate on main.
D6 now passes all nine items against the installed Desktop, launched from the
Start menu, using the real SiliconFlow provider (openai /
https://api.siliconflow.cn/v1 / deepseek-ai/DeepSeek-V3.2) with the key read
only from the Windows keyring. No Fake provider, no temporary environment
variable.

Newly verified this pass:

- uninstall/reinstall round trip, 10/10. Both NSIS packages are perMachine, so
  each direction runs as an elevated child; an unelevated session driving
  uninstall.exe fails with WinError 740. %APPDATA%\Rove stayed at 146 files /
  11204219 bytes across all three stages, so uninstall preserves user data.
- reinstall plus Start-menu relaunch restores workspace, all four sessions with
  their statuses, the provider profile as a keyring reference, and the terminal
  run binding of the successful real run.
- SSE disconnect/reconnect, 5/5. after=40 resumed at exactly seq 41 and drained
  to 1148: no duplicate seqs, one run_completed, no gaps, one run per job.
- restart recovery, 10/10, including artifact sha256 digests. /jobs/{id}/state
  returns 404 by design; terminal state comes from the durable report.

Replaces the stale blocking note that claimed installation was impossible
without an administrator session, and corrects the bundle-output path: the build
redirected CARGO_TARGET_DIR to C: for disk space, so artifacts landed outside
the in-repo target/release/bundle/.

Records four product defects found while running the gate (needs_attention
deadlock, project config never loaded on the API path, unreachable
max_model_turns_per_step, product UI cannot select an agent profile). None are
fixed here: section 6 forbids this branch from unilaterally changing the Core
Agent loop, Provider wire protocol, or Tool Registry permissions.

Remaining gaps stated honestly: the section 10.1 A gate still must run on merged
main, Playwright e2e was not run here, and no screenshots were captured.
@AllureCurtain AllureCurtain changed the title feat(desktop): native provider onboarding via shared service (D1-D5; D6 unverified) feat(desktop): real-use Desktop product path (D1-D6 complete on Windows) Aug 26, 2026
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