Skip to content

Fix #467: ambiguous '-app' parsing and silent partial process matches#477

Merged
nmetulev merged 5 commits into
mainfrom
fix/issue-467-partial-match
Apr 21, 2026
Merged

Fix #467: ambiguous '-app' parsing and silent partial process matches#477
nmetulev merged 5 commits into
mainfrom
fix/issue-467-partial-match

Conversation

@nmetulev
Copy link
Copy Markdown
Member

Fixes #467.

Problem

winapp ui inspect -app tauri-app --depth 6 was silently inspecting the wrong app (e.g. Microsoft Teams) instead of the Tauri app, with no indication anything was wrong.

Two compounding issues:

  1. POSIX short-option bundling. -a is a registered short alias of --app, so System.CommandLine parsed -app as the short option -a with attached value pp (POSIX -aValue form). Result: app="pp", selector="tauri-app". Zero unmatched tokens, so TreatUnmatchedTokensAsErrors had nothing to reject.
  2. Silent partial process-name matching. UiSessionService.TryResolveProcess("pp") falls back to p.ProcessName.Contains("pp", OrdinalIgnoreCase). Many running processes match (ApplicationFrameHost, etc.); whichever happens to have a foreground/main window wins. The selection was logged at Debug only, so users had no signal that a partial match had occurred.

Fix

  • Disable POSIX bundling globally via a shared WinAppParserConfiguration.Default (EnablePosixBundling = false), wired into the two production parse sites (Program.cs, CompleteCommand.cs). Tests use long-form options exclusively and are unaffected. Searched the repo for attached-value short-option usage (-w7932630, -aFoo, etc.) — none in docs, samples, scripts, or skills.
  • Add OptionTypoValidator as defense-in-depth. With bundling off, the parser would otherwise consume -app as the positional selector argument and emit Unrecognized command or argument 'tauri-app' — which points at the wrong token. The validator inspects the parsed command's long-option namespace, detects single-dash tokens that match a known long option (e.g. -app--app), and exits with a clearer message before invocation:
    Unknown option '-app'. Did you mean '--app'?
    (Single-dash flags are reserved for short aliases like '-a'. Long options use a double dash.)
    
    Honors TreatUnmatchedTokensAsErrors=false so pass-through commands like tool and ms-store are unaffected. Skips negative numbers and tokens after --.
  • Promote partial-match logging from DebugInformation in UiSessionService so users see when a short/typoed --app value resolved to an unrelated process, with the matched PID/process name and a hint to use -w <HWND> or the full process name to disambiguate. Same change for the auto-window-selection path when one process owns multiple windows.

Verification

  • New OptionTypoValidatorTests (7 cases): typo detection, attached-value form (-app=foo), valid short/long options, unknown clusters with no matching long, -- terminator, negative numbers.
  • Full test suite: 771/771 passing.
  • Manual smoke tests:
    • -app something → friendly typo error, exit 1 ✅
    • -a something (valid short) → works ✅
    • --app something → works ✅
    • --help and ui inspect --help → unaffected ✅
  • scripts/build-cli.ps1 regenerated CLI schema and skills cleanly with no surface changes.

nmetulev and others added 2 commits April 20, 2026 12:26
Fixes #467.

System.CommandLine treats '-app' as the short option '-a' with attached value 'pp' (POSIX bundling). Combined with UiSessionService.TryResolveProcess's silent partial-name fallback, that meant 'winapp ui inspect -app tauri-app' could resolve to an unrelated process (e.g. Microsoft Teams) without any indication.

- Add OptionTypoValidator to flag tokens like '-app' when '--app' exists on the resolved command path, and reject them with a helpful error before invocation. Skipped for commands that intentionally pass through unknown tokens (tool, ms-store).

- Promote partial-match and auto-window-selection log messages from Debug to Information in UiSessionService so users see when 'pp' got partial-matched to ApplicationFrameHost or when one of multiple windows was auto-selected.

- Add OptionTypoValidatorTests covering positive/negative cases, attached-value form, '--' terminator, and negative numbers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Per follow-up on #467: instead of relying solely on the OptionTypoValidator heuristic, disable EnablePosixBundling at the parser level via a shared WinAppParserConfiguration so that '-app tauri-app' can never be silently reinterpreted as '-a pp'.

- Add WinAppParserConfiguration.Default with EnablePosixBundling = false.

- Wire it into the two production parse sites: Program.cs (main parse + --help fallback) and CompleteCommand.cs (shell completion). Tests parse with long-form options only and are unaffected.

- Keep OptionTypoValidator as defense-in-depth: with bundling off, '-app foo' would otherwise produce 'Unrecognized command or argument foo' from System.CommandLine, which points at the wrong token. The validator still surfaces the clearer 'Did you mean --app?' message before invocation.

- Update the validator's secondary error line and code comments to reflect the new behavior. Verified with the full 771-test suite (all green) and manual smoke tests of -app, -a, --app, and --help paths.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 20, 2026 21:13
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses issue #467 where winapp ui inspect -app ... could be mis-parsed (POSIX short-option bundling) and then silently resolve to the wrong process via partial process-name matching, leading to inspecting an unintended app.

Changes:

  • Introduces a shared WinAppParserConfiguration.Default with EnablePosixBundling = false and wires it into the main CLI parse sites.
  • Adds OptionTypoValidator to detect single-dash long-option typos (e.g. -app--app) and emit a clearer error message before invocation.
  • Promotes partial-match and auto-window selection logging to Information to surface ambiguous/heuristic resolution to users, and adds unit tests for the typo validator.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
src/winapp-CLI/WinApp.Cli/Services/UiSessionService.cs Surfaces auto-window selection and partial process-name match behavior via Information logs.
src/winapp-CLI/WinApp.Cli/Program.cs Uses shared parser config; adds pre-invocation typo detection/error messaging for -app-style mistakes.
src/winapp-CLI/WinApp.Cli/Helpers/WinAppParserConfiguration.cs New centralized ParserConfiguration disabling POSIX bundling.
src/winapp-CLI/WinApp.Cli/Helpers/OptionTypoValidator.cs New helper to detect single-dash long-option typos while respecting pass-through commands and --.
src/winapp-CLI/WinApp.Cli/Commands/CompleteCommand.cs Ensures completion parsing uses the same shared parser configuration as the main entrypoint.
src/winapp-CLI/WinApp.Cli.Tests/OptionTypoValidatorTests.cs Adds coverage for typo detection scenarios and edge cases.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/winapp-CLI/WinApp.Cli.Tests/OptionTypoValidatorTests.cs
Comment thread src/winapp-CLI/WinApp.Cli.Tests/OptionTypoValidatorTests.cs
Comment thread src/winapp-CLI/WinApp.Cli/Program.cs Outdated
Comment thread src/winapp-CLI/WinApp.Cli.Tests/OptionTypoValidatorTests.cs
Comment thread src/winapp-CLI/WinApp.Cli.Tests/OptionTypoValidatorTests.cs
Comment thread src/winapp-CLI/WinApp.Cli.Tests/OptionTypoValidatorTests.cs
Comment thread src/winapp-CLI/WinApp.Cli.Tests/OptionTypoValidatorTests.cs
Comment thread src/winapp-CLI/WinApp.Cli/Services/UiSessionService.cs Outdated
Comment thread src/winapp-CLI/WinApp.Cli.Tests/OptionTypoValidatorTests.cs
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 20, 2026

Build Metrics Report

Binary Sizes

Artifact Baseline Current Delta
CLI (ARM64) 30.66 MB 30.66 MB 📈 +4.5 KB (+0.01%)
CLI (x64) 31.02 MB 31.02 MB 📈 +4.0 KB (+0.01%)
MSIX (ARM64) 12.93 MB 12.94 MB 📈 +9.4 KB (+0.07%)
MSIX (x64) 13.74 MB 13.74 MB 📈 +3.1 KB (+0.02%)
NPM Package 26.89 MB 26.90 MB 📈 +1.3 KB (+0.00%)
NuGet Package 26.98 MB 26.98 MB 📈 +3.5 KB (+0.01%)
VS Code Extension 19.72 MB 19.72 MB 📈 +3.0 KB (+0.02%)

Test Results

780 passed, 1 skipped out of 781 tests in 414.7s (+7 tests, -16.8s vs. baseline)

Test Coverage

21.4% line coverage, 36.5% branch coverage · ✅ no change vs. baseline

CLI Startup Time

45ms median (x64, winapp --version) · ✅ +6ms vs. baseline


Updated 2026-04-21 18:05:19 UTC · commit 73c1ef3 · workflow run

1. Gate OptionTypoValidator on parseResult.Errors.Count > 0 (Program.cs)

   so commands that legitimately accept '-foo'-shaped positional values

   don't get a false-positive typo error. The original bug case still

   triggers because POSIX bundling is now off, so '-app foo' produces an

   unmatched-token parse error before the validator runs.

2. Use WinAppParserConfiguration.Default in OptionTypoValidatorTests so

   tests parse with the same configuration as production (POSIX bundling

   disabled). Without this, tests would not catch a regression in the

   parser configuration.

3. Rename duplicate {Hwnd} placeholder in UiSessionService auto-select

   log template to {ExplicitHwnd} so structured logging properties are

   unambiguous.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@nmetulev
Copy link
Copy Markdown
Member Author

Addressed all three distinct review points in 9c13294:

  1. OptionTypoValidator now gated on parseResult.Errors.Count > 0 (Program.cs) so commands that legitimately accept -foo-shaped positional values can't trigger a false-positive typo error. The original -app tauri-app bug case still triggers because POSIX bundling is off -> unmatched-token parse error -> validator runs -> friendly suggestion.
  2. All seven rootCommand.Parse(args) calls in OptionTypoValidatorTests now use WinAppParserConfiguration.Default, matching production parsing behavior.
  3. Duplicate {Hwnd} placeholder in UiSessionService.AutoSelectWindow log template renamed to {ExplicitHwnd} so structured logging properties are unambiguous.

Manual smoke check (Release publish):

  • ui inspect -app tauri-app --depth 6 -> friendly typo error, exit 1 ✅
  • ui inspect -a nonexistent-app -> normal not-found path, exit 1 ✅

Full suite still 771/771 passing.

Switching back to my other branch now.

@nmetulev nmetulev merged commit fafff27 into main Apr 21, 2026
11 checks passed
@nmetulev nmetulev deleted the fix/issue-467-partial-match branch April 21, 2026 17:54
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.

winapp ui: inspect returning wrong information for wrong app

3 participants