Skip to content

Restore generated option API compatibility - #3935

Open
thomhurst wants to merge 14 commits into
mainfrom
issue-3912-options-api-compat
Open

Restore generated option API compatibility#3935
thomhurst wants to merge 14 commits into
mainfrom
issue-3912-options-api-compat

Conversation

@thomhurst

Copy link
Copy Markdown
Owner

Summary

  • roll back the nine published generated-option regressions to their pre-regeneration API baselines
  • preserve removed optional properties as obsolete aliases and stable required-member names on future generations
  • reject type replacements, CLI identity changes, optional-to-required changes, and required-constructor changes before generated files are overwritten
  • compare emitted option types, including optional-arity CliOptionValue shapes

Validation

  • GeneratorHardeningTests: 60 passed
  • CodeGeneratorOrchestratorTests: 16 passed
  • OptionsGenerator Release build: 0 warnings/errors
  • Grype, Rust, Buildah, Docker, Trivy, Kubernetes, and Skopeo solution builds: passed
  • Pulumi and Flux local builds reached the repository's 2 GB agent guard; limits were not raised or retried
  • rollback audit: all affected paths match their pre-regeneration baselines, except the compatible optional Kustomize Dir addition already merged in Keep Kustomize build path optional #3928

Closes #3912

@greptile-apps

greptile-apps Bot commented Aug 10, 2026

Copy link
Copy Markdown

Too many files changed for review (143 files, 100 file limit).

Bypass the limit by tagging @greptile-apps to review.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@thomhurst, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 2 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 790955e9-cfb0-4377-a664-e3a0ebf43a54

📥 Commits

Reviewing files that changed from the base of the PR and between 7479886 and fe4f6d2.

⛔ Files ignored due to path filters (61)
  • src/ModularPipelines.Buildah/Options/BuildahManifestOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Buildah/Options/BuildahSourceOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Docker/Options/DockerComposeBuildOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Docker/Options/DockerComposeConfigOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Docker/Options/DockerComposeEventsOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Docker/Options/DockerComposeExecOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Docker/Options/DockerComposePublishOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Docker/Options/DockerComposeStartOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Docker/Options/DockerComposeUpOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Generated/Flux.CommandCoverage.json is excluded by !**/generated/**
  • src/ModularPipelines.Flux/Options/FluxBootstrapOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxBuildOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxCreateImageOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxCreateOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxCreateSecretOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxCreateSourceOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxDebugOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxDeleteImageOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxDeleteOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxDeleteSourceOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxDiffOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxExportArtifactOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxExportImageOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxExportOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxExportSourceOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxGetArtifactsOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxGetImagesOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxGetOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxGetSourcesOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxListOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxPluginOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxPullOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxPushOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxReconcileImageOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxReconcileOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxReconcileSourceOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxResumeImageOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxResumeOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxResumeSourceOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxSuspendImageOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxSuspendOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxSuspendSourceOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxTagOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxTreeArtifactOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxTreeOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Flux/Options/FluxTriggerOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Grype/Options/GrypeDbOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Grype/Options/GrypeDbSearchOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Kubernetes/Extensions/KustomizeExtensions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Kubernetes/Options/KustomizeCfgCatOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Kubernetes/Options/KustomizeCfgCountOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Kubernetes/Options/KustomizeCfgTreeOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Kubernetes/Options/KustomizeFnRunOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Pulumi/Generated/Pulumi.CommandCoverage.json is excluded by !**/generated/**
  • src/ModularPipelines.Pulumi/Options/PulumiNewOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Pulumi/Options/PulumiProjectNewOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Trivy/Options/TrivyModuleOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Trivy/Options/TrivyPluginOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Trivy/Options/TrivyRegistryOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Trivy/Options/TrivyVexOptions.Generated.cs is excluded by !**/*.generated.*
  • src/ModularPipelines.Trivy/Options/TrivyVexRepoOptions.Generated.cs is excluded by !**/*.generated.*
📒 Files selected for processing (19)
  • docs/docs/mp-packages/cli/kustomize.md
  • tools/ModularPipelines.OptionsGenerator/src/ModularPipelines.OptionsGenerator.Tests/Generators/CodeGeneratorOrchestratorTests.cs
  • tools/ModularPipelines.OptionsGenerator/src/ModularPipelines.OptionsGenerator.Tests/Generators/GeneratorHardeningTests.cs
  • tools/ModularPipelines.OptionsGenerator/src/ModularPipelines.OptionsGenerator.Tests/Scrapers/CosignCliScraperTests.cs
  • tools/ModularPipelines.OptionsGenerator/src/ModularPipelines.OptionsGenerator.Tests/Scrapers/DockerCliCompatibilityTests.cs
  • tools/ModularPipelines.OptionsGenerator/src/ModularPipelines.OptionsGenerator.Tests/Scrapers/TrivyCliScraperTests.cs
  • tools/ModularPipelines.OptionsGenerator/src/ModularPipelines.OptionsGenerator/Generators/CodeGeneratorOrchestrator.cs
  • tools/ModularPipelines.OptionsGenerator/src/ModularPipelines.OptionsGenerator/Generators/GeneratedApiCompatibilityPreserver.cs
  • tools/ModularPipelines.OptionsGenerator/src/ModularPipelines.OptionsGenerator/Generators/GeneratorUtils.cs
  • tools/ModularPipelines.OptionsGenerator/src/ModularPipelines.OptionsGenerator/Generators/GlobalOptionsBaseGenerator.cs
  • tools/ModularPipelines.OptionsGenerator/src/ModularPipelines.OptionsGenerator/Generators/InheritedPropertyCollisionResolver.cs
  • tools/ModularPipelines.OptionsGenerator/src/ModularPipelines.OptionsGenerator/Generators/OptionsClassGenerator.cs
  • tools/ModularPipelines.OptionsGenerator/src/ModularPipelines.OptionsGenerator/Generators/SubDomainClassGenerator.cs
  • tools/ModularPipelines.OptionsGenerator/src/ModularPipelines.OptionsGenerator/Models/CliCommandDefinition.cs
  • tools/ModularPipelines.OptionsGenerator/src/ModularPipelines.OptionsGenerator/Models/CliToolDefinition.cs
  • tools/ModularPipelines.OptionsGenerator/src/ModularPipelines.OptionsGenerator/Scrapers/Cli/CobraCliScraper.cs
  • tools/ModularPipelines.OptionsGenerator/src/ModularPipelines.OptionsGenerator/Scrapers/Cli/CosignCliScraper.cs
  • tools/ModularPipelines.OptionsGenerator/src/ModularPipelines.OptionsGenerator/Scrapers/Cli/DockerCliScraper.cs
  • tools/ModularPipelines.OptionsGenerator/src/ModularPipelines.OptionsGenerator/Scrapers/Cli/TrivyCliScraper.cs

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

@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: f46ac6a2c1

ℹ️ 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".

Comment thread src/ModularPipelines.Docker/Options/DockerComposeExecOptions.Generated.cs Outdated
@thomhurst

Copy link
Copy Markdown
Owner Author

Addressed the Docker Compose --no-TTY casing finding in 9168cdb. Targeted generation was also attempted; the compatibility guard correctly stopped on unrelated installed-Docker API drift (DockerLoadOptions.Platform), so no limits were raised and the single backed generated artifact was synchronized. Focused tests and both relevant Release builds are green.

@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: 9168cdb0eb

ℹ️ 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".

Comment thread src/ModularPipelines.Kubernetes/Options/KustomizeCfgCatOptions.Generated.cs Outdated
Comment thread src/ModularPipelines.Buildah/Options/BuildahBuildOptions.Generated.cs Outdated

@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: 9a0d30e311

ℹ️ 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".

Comment thread src/ModularPipelines.Pulumi/Options/PulumiPluginInstallOptions.Generated.cs Outdated
Comment thread src/ModularPipelines.Kubernetes/Services/KustomizeEditAdd.Generated.cs Outdated

@claude claude 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.

Code review

Reviewed the core logic of this PR: GeneratedApiCompatibilityPreserver (new), its wiring into CodeGeneratorOrchestrator.GenerateForToolAsync, and the supporting scraper/test changes. The regression-rollback and the new hardening tests (ApiCompatibilityPreserver_* in GeneratorHardeningTests.cs) look solid in isolation — type-change, optional→required, and required-member add/remove are all well covered with clear violation messages.

Two architectural concerns on the compatibility-preservation design itself:

1. Ordering hazard: Preserve runs before InheritedPropertyCollisionResolver.Resolve, so its "preserved" name isn't guaranteed final

In CodeGeneratorOrchestrator.GenerateForToolAsync:

var compatibleTool = GeneratedApiCompatibilityPreserver.Preserve(tool with { ... }, outputDirectory);
var toolDefinition = InheritedPropertyCollisionResolver.Resolve(
    ExecutablePrerequisiteCatalog.PrepareForGeneration(compatibleTool));

RestoreRequiredMemberNames mutates Options/PositionalArguments property names to match the baseline before InheritedPropertyCollisionResolver.Resolve runs. Resolve unconditionally renames any property whose name matches one of the seven reserved names on CommandLineToolOptions (Tool, CommandParts, Arguments, AdditionalArguments, ArgumentsContainToolOptions, ArgumentsContainOptionTerminator, RunSettings) — see InheritedPropertyCollisionResolver.ResolveName. If a restored/baseline name ever lands on one of those reserved names (e.g. a scraper fix renames a property such that its CLI-identity match now resolves to a baseline name of Arguments), Resolve will silently rename it again after Preserve already returned success with zero violations — quietly reintroducing exactly the kind of breaking rename this PR exists to prevent, with no test coverage of the composed pipeline (every ApiCompatibilityPreserver_* test calls Preserve and OptionsClassGenerator directly, never through Resolve).

Why this matters architecturally: the whole point of GeneratedApiCompatibilityPreserver is to make a guarantee ("this public property name will not change"), but two independent, mutually-unaware stages both own property renaming and run in an order where the later stage can undo the earlier stage's guarantee. That's a layering violation — a component that promises API stability shouldn't be upstream of another component that can still rename the API.

Suggested fix: either (a) run Preserve last, comparing the baseline against the fully-resolved (post-collision) property set so what it returns really is final, or (b) merge the two into a single naming-resolution pass that's aware of both the reserved-name constraint and the compatibility baseline, or at minimum (c) add an orchestrator-level (or paired) test that exercises Preserve followed by Resolve together, so a future regression here would actually be caught.

2. Baseline is derived by re-parsing the generator's own previous output via ad-hoc Roslyn syntax-tree scraping

GeneratedApiCompatibilityPreserver.ReadBaseline/ReadProperties re-parses the committed *.Generated.cs files with CSharpSyntaxTree.ParseText and walks RecordDeclarationSyntax/PropertyDeclarationSyntax nodes, inferring required-ness from constructor parameters vs. properties, and recovering CLI identity from CliArgument/CliOption/CliFlag attribute text. This makes the compatibility contract implicit in — and fully coupled to — the incidental shape of the generator's own emitted source text, rather than an explicit, versioned artifact.

Why this matters architecturally: any future change to how the generator formats or structures emitted code (a new attribute wrapper, an additional interface/base type, a different accessor style) can silently break baseline extraction with no compiler-level signal — the failure mode is "the preserver just stops seeing that property as part of the baseline," which is the opposite of what a compatibility gate should do on interpretation failure. This is effectively a hand-rolled, narrower version of the public-API-tracking pattern .NET already has established tooling for (Microsoft.CodeAnalysis.PublicApiAnalyzers's PublicAPI.Shipped.txt), which stores the contract as an explicit, diffable, structured file rather than deriving it by re-parsing generated source. Consider emitting a small explicit baseline manifest (e.g. JSON keyed by class/property with type + required + CLI-identity fields) as a generation byproduct and diffing against that, instead of syntax-tree-mining the .Generated.cs files. That decouples "what API did we promise" from "how does the generator currently choose to format its output," and would surface a parsing/shape mismatch as a loud, structured diff rather than a silent gap in coverage.

Everything else (the DockerCliScraper/CobraCliScraper NormalizeOptionSwitchName hook for docker compose exec --no-TTY, and the rollback of the nine published option files) looks like a straightforward, well-targeted fix.

Keep current constructor and optional-value APIs while extending baseline preservation to global and supplemental options.
@thomhurst

Copy link
Copy Markdown
Owner Author

Addressed every exact-head finding in dbe256f0c7d97ab9bb0045e5c9b4b7a9a3eb4d66:

  • preserved KustomizeCfgCatOptions(string Dir) plus the parameterless compatibility call shape
  • preserved Buildah Pull as CliOptionValue? with optional arity
  • extended baseline validation/compatibility aliases to merged scraped + supplemental global options
  • updated inherited-name resolution for global alias forwarding targets
  • split the complexity-28 compatibility method into focused helpers (CodeFactor finding)

Validation:

  • GeneratorHardeningTests: 63/63
  • CodeGeneratorOrchestratorTests: 16/16
  • OptionsGenerator Release: 0 warnings/errors
  • Buildah Release: 0 warnings/errors
  • Kubernetes Release: 0 warnings/errors
  • changed-file whitespace verification: clean

The broad generator format gate remains blocked by unrelated pre-existing whitespace/info diagnostics (first IHelpTextCache.cs:59); no identical retry was made.

@codex review exact head dbe256f0c7d97ab9bb0045e5c9b4b7a9a3eb4d66 and submit approval if clean.
@claude review exact head dbe256f0c7d97ab9bb0045e5c9b4b7a9a3eb4d66 and submit approval if clean.

@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: dbe256f0c7

ℹ️ 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".

Comment thread src/ModularPipelines.Kubernetes/Options/KustomizeCfgGrepOptions.Generated.cs Outdated
Comment thread src/ModularPipelines.Skopeo/Options/SkopeoCopyOptions.Generated.cs Outdated
Comment thread src/ModularPipelines.Pulumi/Options/PulumiEnvDiffOptions.Generated.cs Outdated
@thomhurst

Copy link
Copy Markdown
Owner Author

Exact head 08f5dbc validation:

  • OptionsGenerator tests: 818/818
  • OptionsGenerator Release: 0 warnings, 0 errors
  • Kubernetes Release: 0 warnings, 0 errors
  • Skopeo Release: 0 warnings, 0 errors
  • Buildah Release: 0 warnings, 0 errors
  • Rust Release: 0 warnings, 0 errors
  • narrow whitespace verification: clean
  • 55 affected checked-in generated option/service files match main exactly; no public-member deletions remain

Pulumi and Flux solution builds each exceeded the repository's fixed 2 GB local agent guard (2376/2278 MB and 2452 MB respectively), so they were not retried; CI owns those expensive checks.

@thomhurst

Copy link
Copy Markdown
Owner Author

@codex review exact head 08f5dbc

@thomhurst

Copy link
Copy Markdown
Owner Author

@claude review exact head 08f5dbc

@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: 08f5dbc4bf

ℹ️ 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".

@thomhurst

Copy link
Copy Markdown
Owner Author

Addressed all three review findings in b8699c4: reject setter-breaking optional-to-required changes, restore required constructor contract order, and preserve former Deconstruct overloads across regeneration. Validation: GeneratorHardeningTests 72/72 passed; ModularPipelines.OptionsGenerator.slnx Release build passed with 0 warnings and 0 errors.

@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: b8699c461e

ℹ️ 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".

@thomhurst

Copy link
Copy Markdown
Owner Author

Addressed the latest exact-head P1 and CodeFactor finding in 91f7247:

  • reject command option APIs that disappear from the generated facade before stale-file cleanup
  • retain current command-group aliases in the comparison
  • scope facade discovery by target namespace so prefix-related external tools sharing one output directory remain isolated
  • split PreserveBaselineProperty complexity 19 into focused validation logic

Validation:

  • OptionsGenerator tests: 823/823
  • OptionsGenerator Release build: 0 warnings, 0 errors
  • touched-file whitespace verification: clean

@thomhurst

Copy link
Copy Markdown
Owner Author

@codex review commit 91f7247

@thomhurst

Copy link
Copy Markdown
Owner Author

@claude review commit 91f7247

@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: 91f724799c

ℹ️ 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".

@thomhurst

Copy link
Copy Markdown
Owner Author

Addressed shared-package facade ownership in a2e4b80. Validation: GeneratorHardeningTests 75/75 passed; ModularPipelines.OptionsGenerator.slnx Release build passed with 0 warnings and 0 errors.

@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: a2e4b807d4

ℹ️ 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".

Track declaring type, method name, and options type so leaf commands retain named facades when they gain children and other method moves fail validation.
@thomhurst

Copy link
Copy Markdown
Owner Author

Addressed leaf-command facade moves in ded2814. Named facades are preserved when children appear, and compatibility validation now compares declaring type + method + options type. Hardening tests 76/76; Release build clean.

@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: ded2814206

ℹ️ 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".

Comment thread src/ModularPipelines.Flux/Options/FluxBootstrapGitOptions.Generated.cs Outdated
@thomhurst

Copy link
Copy Markdown
Owner Author

Addressed the latest exact-head P2 in 5d4fea6255f7aca026df39e133f2fe766c51192a: all nine stale SecretValue markers were removed from Flux PrivateKeyFile and Pulumi GitAuthSshPrivateKeyPath generated options, matching the generator's existing IsFilePathOption contract.

Validation: GeneratorUtilsTests 122/122; OptionsGenerator Release build 0 warnings/errors; no added private-key path secret markers remain. Flux/Pulumi full solution builds were not repeated because the prior fixed-limit attempts already exceeded the repository's 2 GB agent guard. All 25 review threads audited; zero unresolved.

@codex review exact head 5d4fea6

@claude review exact head 5d4fea6 and submit approval if clean.

@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: 5d4fea6255

ℹ️ 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".

/// <summary>
/// specify a path to config file for secret scanning (default "trivy-secret.yaml")
/// </summary>
[SecretValue]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid redacting Trivy secret-config paths

When callers set SecretConfig, this marker registers the ordinary config-file path as secret material and redacts its occurrences from command diagnostics. Fresh evidence beyond the fixed private-key-path thread is that the exact tree still adds this marker to six Trivy option records even though their descriptions explicitly say “path to config file”; the Cobra scraper calls IsSecretOption without its available description, bypassing the path check. Pass the description through or otherwise classify --secret-config as a path so regenerated files omit these markers.

AGENTS.md reference: AGENTS.md:L164-L168

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in 36da58a. Cobra secret classification now receives the parsed description, so GeneratorUtils recognizes --secret-config as a documented path. Regenerated Trivy 0.70.0 output removes [SecretValue] from all six affected records. The regeneration also preserves shipped command-group operands and passthrough positions. Trivy tests 11/11, Cosign tests 4/4; OptionsGenerator and Trivy Release builds are clean.

@thomhurst

Copy link
Copy Markdown
Owner Author

Fixed in 36da58a. Cobra secret classification now receives the parsed description, so GeneratorUtils recognizes --secret-config as a documented path. Regenerated Trivy 0.70.0 output removes [SecretValue] from all six affected records. The regeneration also preserves shipped command-group operands and passthrough positions. Trivy tests 11/11, Cosign tests 4/4; OptionsGenerator and Trivy Release builds are clean.

@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: 36da58ad83

ℹ️ 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".

Comment on lines +816 to +819
methods.Add(new GeneratedFacadeMethod(
declaringType,
method.Identifier.ValueText,
optionsType.TrimEnd('?')));

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 Preserve parameterless facade calls when required members are added

When an existing command without required members later gains a required option or operand, BuildOptionsParameter changes its facade from FooOptions? options = null to required FooOptions options. This baseline identity strips nullability and records neither the default value nor parameter optionality, so RejectRemovedFacadeMethods considers the method unchanged even though existing calls such as FooAsync() no longer compile; preserve an overload/default alongside the parameterless compatibility options constructor.

AGENTS.md reference: AGENTS.md:L164-L168

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in 14a6a28. Baseline facade parsing now records whether the options parameter had a default; matching commands preserve that optional contract even after gaining required members. Generated implementations use the already-preserved parameterless compatibility constructor when callers omit options, and alias facades share the same requirement decision. Regression passes; GeneratorHardeningTests pass 77/77; OptionsGenerator Release build is clean.

@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: 14a6a28119

ℹ️ 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".

Comment on lines +50 to +53
Commands = compatibleTool.Commands
.Select(command => baseline.TryGetValue(command.ClassName, out var commandBaseline)
? Preserve(command, commandBaseline.Properties, commandBaseline.Constructors)
: command)

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 Preserve constructors on aliased option records

When a command exposed through a public command-group alias gains a required member, this pass only applies the baseline keyed by the canonical command.ClassName; the corresponding alias baseline (for example, DockerBuilder*Options) is never processed. GenerateCompatibilityOptionsAlias then emits only the current required constructor, so existing calls to the alias's previous constructor stop compiling even though the canonical options record receives a compatibility constructor. Preserve alias constructor baselines as well.

AGENTS.md reference: AGENTS.md:L164-L168

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in fe4f6d2. Compatibility preservation now reads each generated command-group alias baseline, records alias-specific constructor history (including the generated base(...) primary constructor), maps aliased enum parameter types through the shared generator helper, and emits retained this(...) overloads on the alias record. Regressions cover parameterless-to-required and one-to-two required constructor evolution. GeneratorHardeningTests pass 79/79; OptionsGenerator Release build is clean.

@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: fe4f6d2eeb

ℹ️ 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".

Comment on lines +110 to +114
PreserveCompatibilityConstructors(
aliasBaseline.Properties,
aliasBaseline.Constructors,
currentRequired,
compatibilityConstructors);

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 Preserve aliased enum properties during regeneration

When an enum-valued option is removed or ceases to be recognized as an enum, this alias pass preserves only constructors. For example, a DockerBuilder*Options property currently typed with a DockerBuilder* enum disappears even though the canonical property is retained as an obsolete compatibility member with the incompatible DockerBuildx* enum type, breaking existing alias consumers. Validate and retain the alias record's declared enum wrapper properties and corresponding alias enum types as well as its constructors.

AGENTS.md reference: AGENTS.md:L164-L168

Useful? React with 👍 / 👎.

Comment on lines +750 to +755
var root = CSharpSyntaxTree.ParseText(File.ReadAllText(path)).GetRoot();
foreach (var declaration in root.DescendantNodes().OfType<RecordDeclarationSyntax>())
{
baseline[declaration.Identifier.ValueText] = new GeneratedApiBaseline(
ReadProperties(declaration),
ReadCompatibilityConstructors(declaration));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve public enum members in the generated baseline

When upgraded CLI help removes or renames one documented enum value while leaving the option itself intact, this baseline scan ignores the generated enum declaration and therefore accepts deletion of its public member. EnumGenerator then emits only the newly scraped values, so source using the old enum member no longer compiles even though the option record passes compatibility validation; include generated enum names, members, CLI values, and stable numeric values in the baseline check.

AGENTS.md reference: AGENTS.md:L164-L168

Useful? React with 👍 / 👎.

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.

OptionsGenerator regression: current regenerations break public APIs

1 participant