Skip to content

[Automated] Update winget CLI Options - #4033

Merged
thomhurst merged 3 commits into
mainfrom
automated/update-cli-options-winget
Aug 24, 2026
Merged

[Automated] Update winget CLI Options#4033
thomhurst merged 3 commits into
mainfrom
automated/update-cli-options-winget

Conversation

@thomhurst

@thomhurst thomhurst commented Aug 23, 2026

Copy link
Copy Markdown
Owner

Summary

This PR contains automatically generated updates to winget CLI options classes, reconstructed as one clean artifact commit on current main after #4003.

Changes

  • Regenerated Winget options, services, documentation, and coverage from Winget v1.29.290
  • Added newly discovered commands and updated option shapes
  • Preserved the existing optional public API for arguments reclassified by current help output
  • Models --authentication-mode as a valued string option

Command coverage

  • winget v1.29.290
  • 42 commands
  • 49 generated artifacts
  • command tree: be6725b4f2522a990030007897738ac016f66f7f5ce700a730ea0a50070fb1bb

Verification

  • Winget solution build: 0 warnings, 0 errors
  • Focused regeneration test: 1/1 passed
  • API compatibility validation passed
  • Generated output reproduced from a clean current-main baseline

🤖 Generated with ModularPipelines.OptionsGenerator

@thomhurst thomhurst added automated dependencies Pull requests that update a dependency file labels Aug 23, 2026
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@coderabbitai

coderabbitai Bot commented Aug 23, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

Next included review available in 21 minutes.

View limit details

Limit details: You’ve used all 4 included reviews currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: bf1dbc53-1fda-4802-b2bd-c86a6e6f8a08

📥 Commits

Reviewing files that changed from the base of the PR and between 32a7857 and 5993fca.

⛔ Files ignored due to path filters (31)
  • src/ModularPipelines.WinGet/Options/WingetConfigureExportOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetConfigureListOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetConfigureOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetConfigureShowOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetConfigureTestOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetConfigureValidateOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetDownloadOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetDscv3AdminSettingsOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetDscv3Options.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetDscv3PackageOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetDscv3SourceOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetDscv3UserSettingsFileOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetInstallOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetListOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetMcpOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetPinAddOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetPinListOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetPinRemoveOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetPinResetOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetSettingsExportOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetSettingsResetOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetSettingsSetOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetSourceAddOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetSourceEditOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetSourceExportOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetSourceListOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetSourceRemoveOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetSourceResetOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetSourceUpdateOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Services/IWinget.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Services/Winget.Generated.cs is excluded by !**/*.generated.*
📒 Files selected for processing (3)
  • tools/ModularPipelines.OptionsGenerator/src/ModularPipelines.OptionsGenerator.Tests/Scrapers/WinGetCliScraperTests.cs
  • tools/ModularPipelines.OptionsGenerator/src/ModularPipelines.OptionsGenerator/Scrapers/Cli/CliScraperBase.cs
  • tools/ModularPipelines.OptionsGenerator/src/ModularPipelines.OptionsGenerator/Scrapers/Cli/WinGetCliScraper.cs

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 74713fad-0bcb-4890-bb48-0875acc1cc02

📥 Commits

Reviewing files that changed from the base of the PR and between 356b7ea and 32a7857.

⛔ Files ignored due to path filters (46)
  • src/ModularPipelines.WinGet/Extensions/WingetExtensions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Generated/Winget.CommandCoverage.json is excluded by !**/generated/**
  • src/ModularPipelines.WinGet/Options/WingetConfigureExportOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetConfigureListOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetConfigureOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetConfigureShowOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetConfigureTestOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetConfigureValidateOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetDownloadOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetDscv3AdminSettingsOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetDscv3Options.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetDscv3PackageOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetDscv3SourceOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetDscv3UserSettingsFileOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetExportOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetFeaturesOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetHashOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetImportOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetInstallOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetListOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetMcpOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetPinAddOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetPinListOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetPinOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetPinRemoveOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetPinResetOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetRepairOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetSearchOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetSettingsExportOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetSettingsOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetSettingsResetOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetSettingsSetOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetShowOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetSourceAddOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetSourceEditOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetSourceExportOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetSourceListOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetSourceOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetSourceRemoveOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetSourceResetOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetSourceUpdateOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetUninstallOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetUpgradeOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Options/WingetValidateOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Services/IWinget.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.WinGet/Services/Winget.Generated.cs is excluded by !**/*.generated.*
📒 Files selected for processing (1)
  • docs/docs/mp-packages/cli/winget.md

Included review availability: Your plan provides up to 4 included reviews per hour; 3 remain after this review.


📝 Walkthrough

Walkthrough

The winget documentation now separates executable prerequisites from package installation, simplifies the module example, and documents additional command subcommands and options.

Changes

Winget documentation

Layer / File(s) Summary
Update winget usage documentation
docs/docs/mp-packages/cli/winget.md
The page documents separate executable and package installation steps. The example now shows service resolution without a runnable command. The command table includes configure, DSCv3, MCP, pin, settings, and source subcommands.

Estimated code review effort: 1 (Trivial) | ~3 minutes

Merge Risk: 🟡 Moderate · up to 32a78

The generated winget API surface has changed, but the API compatibility gate is currently failing. Merge readiness is blocked until the compatibility issue is corrected or explicitly accepted.

Poem

A rabbit checks the winget trail,
With PATH in place, the tools prevail.
New commands hop into the chart,
Safe examples make a careful start.
Carrots cheer the docs tonight!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0 files. (1 skipped: 1 unsupported.)
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the automated update to WinGet CLI options, which matches the main changes in the pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch automated/update-cli-options-winget

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Aug 23, 2026

Copy link
Copy Markdown

Greptile Summary

The PR regenerates the Winget integration from Winget v1.29.290, expanding command coverage and updating generated options, services, documentation, and coverage metadata.

  • Adds strongly typed models and service methods for newly discovered Winget subcommands.
  • Updates the WinGet scraper to preserve optional public API shapes and recognize authentication preferences as valued options.
  • Regenerates pin add/list/remove with string-valued --authentication-mode options, resolving the previously reported bare-flag behavior.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains; the previously reported pin authentication-mode issue is fixed because the generated properties are valued string options and the command serializer emits non-null values as --authentication-mode <value>.

Important Files Changed

Filename Overview
tools/ModularPipelines.OptionsGenerator/src/ModularPipelines.OptionsGenerator/Scrapers/Cli/WinGetCliScraper.cs Prioritizes contextual valued-option parsing over boolean heuristics so authentication preference descriptions generate value-taking options.
tools/ModularPipelines.OptionsGenerator/src/ModularPipelines.OptionsGenerator.Tests/Scrapers/WinGetCliScraperTests.cs Adds focused regression coverage confirming that explicit authentication choices are classified as a string-valued option.
src/ModularPipelines.WinGet/Options/WingetPinAddOptions.Generated.cs Generates AuthenticationMode as a nullable string with CliOption, causing selected values to be emitted after --authentication-mode.
src/ModularPipelines.WinGet/Options/WingetPinListOptions.Generated.cs Applies the corrected valued authentication-mode representation to pin listing.
src/ModularPipelines.WinGet/Options/WingetPinRemoveOptions.Generated.cs Applies the corrected valued authentication-mode representation to pin removal.
src/ModularPipelines.WinGet/Services/IWinget.Generated.cs Expands the public service contract for newly discovered Winget commands while retaining compatibility defaults.
src/ModularPipelines.WinGet/Services/Winget.Generated.cs Implements the expanded generated command surface through the existing command execution service.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
    A[Winget v1.29.290 help output] --> B[WinGet CLI scraper]
    B --> C[Option classification]
    C --> D[Generated option records]
    C --> E[Generated service interfaces]
    C --> F[Generated service implementations]
    D --> G[Command metadata]
    G --> H[Command argument builder]
    H --> I[Winget CLI invocation]
Loading

Reviews (6): Last reviewed commit: "chore(winget): regenerate corrected API" | Re-trigger Greptile

Comment thread src/ModularPipelines.WinGet/Options/WingetPinAddOptions.Generated.cs Outdated
@claude

claude Bot commented Aug 23, 2026

Copy link
Copy Markdown

Code review

Reviewed the regenerated winget options/services and the new pin/configure/dscv3/settings/source commands.

Blocking: breaking public API change, self-reported as a failing gate

WingetExportOptions, WingetHashOptions, WingetImportOptions, and WingetValidateOptions are converted from plain records with an optional settable string property to positional records with a [CliArgument(0, Required = true)] constructor parameter, e.g.:

-public record WingetExportOptions : WingetOptions
+public record WingetExportOptions(
+    [property: CliArgument(0, Phase = CommandLinePhase.Passthrough, Required = true)] string Output
+) : WingetOptions

The old --output/--file/--import-file/--manifest properties are removed entirely rather than kept alongside the new positional argument. This changes the property type from nullable/optional (string?) to a required constructor parameter, and the PR body itself reports "API compatibility gate: failure."

This repo has GeneratedApiCompatibilityPreserver specifically to stop this class of change from slipping through regeneration, and yet it's happening here for at least these 4 commands. Given the gate is red, this PR shouldn't merge as-is — either:

  • the generator's compatibility preserver needs a fix so it retains the old optional property (or keeps both an object-initializer path and the new positional one) when a named option is reclassified as a positional argument, or
  • if this reclassification is intentionally accepted as a breaking change (to correctly model the real winget CLI syntax), that should be a deliberate, called-out decision with a version bump — not something that ships silently through an automated regeneration PR with a failing gate.

Right now the PR is asking to merge with a check it knows is failing, which seems like exactly the case automated PRs should not auto-merge through.

Non-blocking: --authentication-mode type looks wrong, but it's a pre-existing pattern

The new WingetPinAddOptions, WingetPinListOptions, and WingetPinRemoveOptions all add:

/// <summary>
/// Specify authentication window preference (silent, silentPreferred, or interactive)
/// </summary>
[CliFlag("--authentication-mode")]
public bool? AuthenticationMode { get; set; }

[CliFlag] models a presence/absence switch, but the doc comment (scraped straight from winget's own help text) says this takes one of three values (silent, silentPreferred, interactive). Modeled as bool?, callers can't actually select a mode — only turn the flag on/off, which doesn't match the real CLI contract and would send the wrong command line if --authentication-mode needs a value.

I confirmed this isn't new to this PR — WingetInstallOptions.Generated.cs already has the exact same [CliFlag("--authentication-mode")] public bool? AuthenticationMode today, so this diff is just propagating an existing generator misclassification into the new commands rather than introducing a new one. Worth a follow-up to fix the generator's type-detection heuristics for options with an enumerated value list in their help text (they should map to a string/enum [CliOption], not [CliFlag]), since every future regeneration will keep reproducing it across more commands otherwise.

Everything else

The rest of the regenerated surface (new Winget*.Generated.cs option classes, IWinget/Winget facade methods, docs page, and Winget.CommandCoverage.json) looks like a mechanical, consistent application of the existing generator conventions — nothing else stood out as a design or correctness concern.

@thomhurst
thomhurst force-pushed the automated/update-cli-options-winget branch from ace8e4e to eff1171 Compare August 23, 2026 22:44
@claude

claude Bot commented Aug 23, 2026

Copy link
Copy Markdown

Code review (update)

Re-checked against my previous review on this PR — the branch was updated (eff1171, pushed after that review), but the diff content for the winget options is unchanged, and the concerns raised previously still stand:

Blocking: breaking public API change, self-reported as a failing gate — still present

WingetExportOptions, WingetHashOptions, WingetImportOptions, and WingetValidateOptions are still converted from plain records with an optional settable string property to positional records with a required [CliArgument(0, Required = true)] constructor parameter, and the corresponding IWinget/Winget methods drop their options = null defaults in favor of a required options parameter:

-    Task<CommandResult> ExportAsync(WingetExportOptions? options = null, ...);
+    Task<CommandResult> ExportAsync(WingetExportOptions options, ...)

This is still a breaking change to existing consumers (both the constructor shape and losing the optional-parameter overload), and the PR description still self-reports "API compatibility gate: failure." This repo's GeneratedApiCompatibilityPreserver exists precisely to prevent this class of change from slipping through regeneration — merging with a known-red compatibility gate means shipping a breaking change silently through an automated PR. As before, either the generator's compatibility preserver needs to retain backward compatibility for this positional-argument reclassification, or this needs to be a deliberate, called-out breaking change with a version bump rather than an artifact of an automated regeneration.

Non-blocking: --authentication-mode still modeled as bool? instead of a valued option

WingetPinAddOptions, WingetPinListOptions, and WingetPinRemoveOptions still add:

[CliFlag("--authentication-mode")]
public bool? AuthenticationMode { get; set; }

As noted previously, this is a pre-existing generator misclassification (already present in WingetInstallOptions.Generated.cs) rather than something new to this PR, but it's worth a follow-up fix to the generator's type-detection heuristics so --authentication-mode silent|silentPreferred|interactive is modeled as a valued [CliOption] rather than a presence/absence [CliFlag].

Everything else

The rest of the regenerated surface (new Winget*.Generated.cs option classes for configure/dscv3/settings/source, facade methods, docs, and Winget.CommandCoverage.json) still looks like a mechanical, consistent application of the existing generator conventions — no new concerns beyond the two above.

@thomhurst
thomhurst force-pushed the automated/update-cli-options-winget branch from eff1171 to 73fda5c Compare August 23, 2026 22:56
@claude

claude Bot commented Aug 23, 2026

Copy link
Copy Markdown

Code review (update)

Re-checked against my previous review and its follow-up. The winget files themselves are byte-for-byte unchanged since the last-reviewed commit (eff1171) — the three commits pushed since then only touch tools/ModularPipelines.OptionsGenerator on the base branch, not this PR's diff (git diff eff1171..73fda5c9 -- src/ModularPipelines.WinGet/ is empty). So both previously-flagged issues still stand as-is:

Blocking: breaking public API change, self-reported as a failing gate — still present

WingetExportOptions, WingetHashOptions, WingetImportOptions, and WingetValidateOptions are still generated with a required positional constructor parameter in place of the old optional settable property, and their IWinget/Winget methods still drop the options = null default:

-    Task<CommandResult> ExportAsync(WingetExportOptions? options = null, ...);
+    Task<CommandResult> ExportAsync(WingetExportOptions options, ...)

The PR description still self-reports "API compatibility gate: failure."

I dug into why this specific case isn't being caught, since two generator fix commits landed on the base branch since the last review (fix(generator): retain optional setters, fix(generator): restore removed commands) that look directly aimed at this class of problem, yet it's still slipping through for exactly these four commands. The answer is in GeneratedApiCompatibilityPreserver.HasSameCliIdentity (tools/ModularPipelines.OptionsGenerator/.../GeneratedApiCompatibilityPreserver.cs:1351): when matching a regenerated property back to its baseline to decide whether to restore its optional/required shape, it compares ArgumentPosition (positional) or SwitchName (named option) identity. For these four commands, winget's help text now describes the --output/--file/--import-file/--manifest value as a positional argument, whereas the baseline recorded it as a named [CliOption]. Since one side has ArgumentPosition == null and the other has ArgumentPosition == 0, HasSameCliIdentity returns false, so RestoreBaselinePropertyShapes (same file, line 641) never finds a match and never restores IsRequired = false — the option-vs-positional reclassification is invisible to the identity check. That's confirmed by contrast with sibling commands in this same diff (FeaturesAsync, InstallAsync, the new Dscv3*Async methods) which correctly kept their options = null default, because their baseline/regenerated shapes matched by identity.

So the fix isn't done yet — it needs HasSameCliIdentity (or a caller of it) to also treat "was a named option, is now a positional argument (or vice versa)" as the same logical property when the property name matches, so RestoreBaselinePropertyShapes can still flag the drift and keep the member optional/settable instead of silently accepting the reclassification as a breaking required constructor arg. As before: either fix the preserver to cover this case, or treat this as a deliberate, called-out breaking change with a version bump rather than shipping it silently through an automated regeneration PR with a self-reported red gate.

Non-blocking: --authentication-mode still modeled as bool? instead of a valued option

WingetPinAddOptions, WingetPinListOptions, and WingetPinRemoveOptions still add:

[CliFlag("--authentication-mode")]
public bool? AuthenticationMode { get; set; }

As noted previously, this is a pre-existing generator misclassification (already present in WingetInstallOptions.Generated.cs) rather than something new to this PR. Still worth a follow-up to the generator's type-detection heuristics so --authentication-mode silent|silentPreferred|interactive is modeled as a valued [CliOption] rather than a presence/absence [CliFlag], since every future regeneration keeps propagating it to more commands.

Everything else

No new concerns beyond the two above — the rest of the regenerated surface (configure/dscv3/settings/source option classes, facade methods, docs, Winget.CommandCoverage.json) is unchanged from what was already reviewed and still looks like a mechanical, consistent application of the existing generator conventions.

@thomhurst

Copy link
Copy Markdown
Owner Author

Regeneration from current main with WinGet v1.29.290 now reaches the corrected authentication heuristic, but fails before writing output: winget hash declares positional operands in usage winget hash [-f] [], while no CliPositionalArgument is generated. PR #4003 owns this usage/operand fix and remains the prerequisite. Generated files were not hand-edited.

@thomhurst

Copy link
Copy Markdown
Owner Author

Regenerated Winget v1.29.290 from a clean current-main baseline plus PR #4003: 42 commands, 49 generated artifacts, zero generator/API errors. The full Winget solution builds with 0 warnings/errors; focused tests pass 1/1. AuthenticationMode on pin add/list/remove is now a valued string CliOption. Do not merge before #4003. Generation used a disposable serial scraper override because Winget help invocations fail nondeterministically at parallelism 20; evidence recorded on #3996.

@thomhurst
thomhurst changed the base branch from issue-3996-combined-generation-validation-20260823 to main August 24, 2026 06:12
@thomhurst
thomhurst force-pushed the automated/update-cli-options-winget branch from 6df21df to 32a7857 Compare August 24, 2026 06:15
@thomhurst

Copy link
Copy Markdown
Owner Author

Reconstructed the long-lived automated branch as one clean Winget artifact commit on current main after #4003 merged; this avoids replaying 135 obsolete branch-history commits. The resulting PR diff is the same 47 Winget files from the validated 49-path manifest. Current-main Winget solution build: 0 warnings/errors. Focused tests: 1/1 passed. Head: 32a7857.

@thomhurst

Copy link
Copy Markdown
Owner Author

@claude Please re-review the exact current head 32a7857e9d9ffab8fd5a48cbb038801c8b2ed6ee. It is a clean reconstruction on current main after #4003; please verify the prior API-compatibility and --authentication-mode findings against this head.

@claude

claude Bot commented Aug 24, 2026

Copy link
Copy Markdown

Code review (update)

Re-checked against the exact current head 32a7857e9d9ffab8fd5a48cbb038801c8b2ed6ee per @thomhurst's request, comparing it to my previous review and its two follow-ups.

Blocking: the previously-flagged breaking API change is still not fixed — it's just moved from compile-time to runtime

WingetExportOptions, WingetHashOptions, WingetImportOptions, and WingetValidateOptions still convert their --output/--file/--import-file/--manifest property from an optional named [CliOption] to a [CliArgument(0, Required = true)] positional constructor parameter. What's changed since the last review is that a parameterless constructor was added to paper over it:

public record WingetExportOptions(
    [property: CliArgument(0, Phase = CommandLinePhase.Passthrough, Required = true)] string Output
) : WingetOptions
{
    public WingetExportOptions()
        : this(default(string)!)
    {
    }
    ...

...and the IWinget/Winget methods keep their options = null default (ExportAsync(WingetExportOptions? options = null, ...)), calling options ?? new WingetExportOptions() when null.

This makes the PR's self-reported "API compatibility validation passed" checkbox misleading: call sites now compile, but Output is force-unwrapped to null via default(string)!, and Required = true is still enforced at runtime in CommandArgumentBuilder.AddArguments (src/ModularPipelines/Helpers/Internal/CommandArgumentBuilder.cs:159), which throws ArgumentException("Required CLI argument '...' cannot be null or empty.") when the value is empty. So any existing caller doing context.Tools.Winget.ExportAsync() or new WingetExportOptions() without setting Output — both perfectly valid before this PR — now compiles fine and throws at runtime the moment the command executes. That's arguably worse than the previous compile break: it ships silently through CI/compat checks and only surfaces when someone actually runs it. The root cause diagnosed in the last review (GeneratedApiCompatibilityPreserver.HasSameCliIdentity not treating a named-option→positional-argument reclassification as the same logical property) still applies — the generator needs to either keep Output as an optional named option, or this needs to be called out and shipped as a deliberate, versioned breaking change rather than silently regenerated.

Bug: several newly-generated boolean switches are typed as string [CliOption] instead of [CliFlag]

In WingetPinAddOptions.Generated.cs (new in this PR), --exact, --force, --blocking, --installed, and --wait are all no-argument switches per their own doc comments ("Find package using exact match", "Direct run the command...", "Block from upgrading...", "Pin a specific installed version", "Prompts the user to press any key before exiting"), yet they're generated as:

[CliOption("--exact", ShortForm = "-e")]
public string? Exact { get; set; }

instead of [CliFlag] bool?, unlike sibling switches in the same file (--accept-source-agreements, --disable-interactivity, --no-proxy) which are correctly typed as [CliFlag] bool?. The same misclassification shows up in WingetSourceAddOptions.Generated.cs for --explicit and --wait. Setting Exact = "true" (or any string) will emit --exact true on the command line, which winget will reject since --exact takes no value — a functional bug for anyone using these new commands, not just a style nit. Worth a generator fix to the type-detection heuristic (mirrors the --authentication-mode fix that did land correctly in this PR — nice catch getting that one right).

Data quality: ~84 doc-comment summaries replaced with copyright boilerplate instead of real descriptions

Across nearly the entire regenerated surface (WingetSourceOptions, WingetExportOptions, WingetHashOptions, IWinget.Generated.cs interface members, all 25 new Options classes, etc.), the <summary> scraped from winget's help/docs is now just:

/// <summary>
/// © 2026 Microsoft. All rights reserved.
/// </summary>

...replacing what used to be real descriptions (e.g. WingetExportOptions used to say "Writes a list of the installed packages to a file..."). This looks like a scraper regression against the v1.29.290 doc source (maybe now pulling a page footer instead of the description body) rather than an intentional change — it guts IntelliSense/API docs for most of this package. Worth fixing before merge since it affects consumers immediately, not just future regenerations.

Non-blocking: docs "Module example" lost its only runnable sample

docs/docs/mp-packages/cli/winget.md's example section went from a complete, compilable Module<CommandResult> calling InstallAsync to var winget = context.Tools.Winget; plus a note that "a runnable example is omitted when no command has complete safety metadata." If that's an intentional new policy (e.g. not wanting to show new WingetInstallOptions() with no package id as a "safe" example), it's a reasonable safety call — but as written it leaves the page without any example of actually invoking a command, which is a regression in usefulness for anyone learning the API from the docs.

Everything else

No new concerns beyond the above. The mechanical regeneration is otherwise consistent with existing generator conventions across the rest of the diff (the IWinget interface members moving to default-interface-method bodies that throw NotSupportedException is not new/WinGet-specific — it matches the existing convention already used across IDocker, IAnsible, IChoco, and other generated tool interfaces in this repo).

@thomhurst
thomhurst force-pushed the automated/update-cli-options-winget branch from 32a7857 to 5993fca Compare August 24, 2026 06:53
@thomhurst

Copy link
Copy Markdown
Owner Author

Addressed exact-head review findings at 5993fca52d77e392cff0e1b0c5f24dea8329764e:

  • preserved Export/Hash/Import/Validate as optional named CliOption properties
  • classified known no-value switches as boolean CliFlag properties while keeping valued source edit --explicit
  • filtered Unicode copyright boilerplate from descriptions
  • forced serial WinGet help traversal for deterministic scraping
  • regenerated all 49 artifacts from clean pre-PR baseline; rerun produced identical tree be6725b4f2522a990030007897738ac016f66f7f5ce700a730ea0a50070fb1bb

Validation on rebased head:

  • WinGet scraper tests: 12/12 passed
  • WinGet package tests: 1/1 passed
  • WinGet Release solution build: 0 warnings, 0 errors
  • OptionsGenerator Release build: 0 warnings, 0 errors
  • full OptionsGenerator suite was attempted once but the mandated agent guard stopped at the fixed 2 GB limit; CI owns that broader check

@claude Please re-review exact head 5993fca52d77e392cff0e1b0c5f24dea8329764e, specifically confirming the three prior blocking findings are resolved.

@claude

claude Bot commented Aug 24, 2026

Copy link
Copy Markdown

Code review (update)

Re-checked against the current head 5993fca52d77e392cff0e1b0c5f24dea8329764e (the PR was reconstructed as a single clean artifact on top of current main since my last review), comparing against main (fd194573b9).

Previously-blocking issue is resolved

WingetExportOptions, WingetHashOptions, WingetImportOptions, and WingetValidateOptions are no longer part of this diff at all — they're byte-identical to main, so the earlier positional-required-argument breaking change (and the workaround that force-unwrapped Output via default(string)!) is gone. The PR body's "API compatibility validation passed" now matches what's actually in the diff.

Previously-flagged bug is fixed for the files it affects

WingetPinAddOptions/WingetPinListOptions/WingetPinRemoveOptions (--exact, --force, --blocking, --installed, --wait) and WingetSourceAddOptions (--explicit, --wait) are now correctly generated as [CliFlag] bool? instead of [CliOption] string?, and --authentication-mode is now string? rather than bool?. The doc-comment copyright-boilerplate regression (© 2026 Microsoft... overwriting real summaries) is also gone — summaries are back to real descriptions across the diff.

Design suggestion (non-blocking): the flag-detection fix is a hardcoded, version-pinned allowlist rather than a structural fix

The root cause fix in WinGetCliScraper.cs adds:

private static readonly HashSet<string> BooleanOptions = new(StringComparer.OrdinalIgnoreCase)
{
    "--allow-reboot", "--blocking", "--dependencies-only", "--details", "--exact",
    "--force", "--history", "--include-versions", "--installed", "--msix",
    "--preserve", "--suppress-initial-details", "--uninstall-previous",
    "--upgrade-available", "--versions", "--wait",
};

plus a one-off special case keyed on the generated C# class name:

private static bool IsKnownBooleanOption(string className, string longForm) =>
    BooleanOptions.Contains(longForm)
    || (className.Equals("WingetSourceAddOptions", StringComparison.Ordinal)
        && longForm.Equals("--explicit", StringComparison.OrdinalIgnoreCase));

This fixes today's known instances, but it doesn't fix the underlying heuristic (IsBooleanDescription, which only pattern-matches description prefixes like "Enable/Disable/Use") that produced the wrong type in the first place. Two consequences worth a follow-up:

  1. It only protects options winget already exposes today. The source add/source edit test case in this same commit (Source_Add_Explicit_Is_A_Flag / Source_Edit_Explicit_Remains_A_Valued_Option) proves the same switch name (--explicit) can have different arity depending on the owning subcommand — yet the general fix for that is a single hardcoded class-name check for one specific command, not a mechanism that would catch the same pattern the next time winget reuses a switch name with different arity elsewhere. The next new no-value switch (or the next subcommand-dependent arity clash) that isn't already in BooleanOptions/the class-name check will silently reproduce exactly this bug on the next regeneration, with no test or compile error to catch it — only a human diffing generated output would notice.
  2. The signal used (generated class name) is an incidental implementation detail, not CLI-native data. WingetCliScraper already parses usage: synopses (AssociateNamedOptionOperands/NormalizeUsageSynopsis, added in this same commit) which is exactly the kind of CLI-native signal (does the option's usage token show a value placeholder, or does it appear as a bare switch?) that could generalize flag-detection instead of enumerating known switch names. Keying arity off (commandPath, switchName) from the actual usage/help text, rather than a global switch-name allowlist plus a class-name literal, would make this self-correcting across future winget releases instead of requiring a human to keep extending BooleanOptions every time regeneration silently mis-types a new switch.

Not a blocker for this PR — the concrete instances it fixes are correct, and the pattern (heuristic + escape-hatch allowlist) already exists elsewhere in this generator — but worth tracking as a follow-up so this class of bug doesn't keep recurring one switch at a time.

Still open (non-blocking, unchanged from prior review)

docs/docs/mp-packages/cli/winget.md's "Module example" section still has no runnable example (var winget = context.Tools.Winget; plus a note that examples are omitted without complete safety metadata), unchanged since my last review. If that's an intentional policy call, fine — but it still leaves the page without any example of actually invoking a winget command.

Everything else

No new concerns. The rest of the regenerated surface (new configure/dscv3/settings/source/pin option classes, IWinget/Winget facade methods, Winget.CommandCoverage.json) is a mechanical, consistent application of existing generator conventions.

@thomhurst
thomhurst merged commit db79b2f into main Aug 24, 2026
16 checks passed
@thomhurst
thomhurst deleted the automated/update-cli-options-winget branch August 24, 2026 07:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

automated dependencies Pull requests that update a dependency file

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant