CommandModelProvider.ValidateUniqueSwitches is the only eager model validation; every other structural error is deferred to render time and only triggers when the property happens to be non-null: GroupValues or CliValuePair options with a non-space separator throw InvalidOperationException mid-build (CommandArgumentBuilder.cs:234-238,394-399), and Optional-arity properties with unsupported types throw only when set. Worse, a [CliFlag] on a property whose value is neither bool nor int is silently dropped with no error at all (AddFlag falls through both branches), and duplicate [CliArgument] positions within a phase are never validated — the stable OrderBy(Position) just renders them in model order.
Since the model is static per type and already cached in GetCommandModel, all of these should be validated once at model construction with messages naming the type and property, turning latent per-value runtime failures (and silent no-ops) into immediate, deterministic errors. The render-time separator messages also omit the declaring type and property name (they name only the switch), which the eager check should fix.
Evidence: src/ModularPipelines/Helpers/Internal/CommandModelProvider.cs:119-140, src/ModularPipelines/Helpers/Internal/CommandArgumentBuilder.cs:144-155,234-238,357-361,394-399,299-304
Raised by the v4 scoping audit round 3 — umbrella #3239.
CommandModelProvider.ValidateUniqueSwitchesis the only eager model validation; every other structural error is deferred to render time and only triggers when the property happens to be non-null: GroupValues or CliValuePair options with a non-space separator throwInvalidOperationExceptionmid-build (CommandArgumentBuilder.cs:234-238,394-399), and Optional-arity properties with unsupported types throw only when set. Worse, a[CliFlag]on a property whose value is neither bool nor int is silently dropped with no error at all (AddFlagfalls through both branches), and duplicate[CliArgument]positions within a phase are never validated — the stableOrderBy(Position)just renders them in model order.Since the model is static per type and already cached in
GetCommandModel, all of these should be validated once at model construction with messages naming the type and property, turning latent per-value runtime failures (and silent no-ops) into immediate, deterministic errors. The render-time separator messages also omit the declaring type and property name (they name only the switch), which the eager check should fix.Evidence:
src/ModularPipelines/Helpers/Internal/CommandModelProvider.cs:119-140,src/ModularPipelines/Helpers/Internal/CommandArgumentBuilder.cs:144-155,234-238,357-361,394-399,299-304Raised by the v4 scoping audit round 3 — umbrella #3239.