Repository navigation
Merge remote-tracking branch 'origin/master' into task/573-devcli-internal-handler-classes-trip-ca1812-in - #393
Merged
StevenTCramer merged 8 commits intoNov 13, 2026
Conversation
…ernal-handler-classes-trip-ca1812-in
…ories (CA1812) The TimeWarp.Mediator generator registers nested [NuruRoute] handlers as AddScoped<Handler>, so consumers compiling DevCli content saw CA1812 on the four internal handlers. After AddGeneratedMediator the Nuru generator now swaps each such registration for a same-lifetime factory that calls the handler's single public constructor. The devcli-consumer-check gate now compiles the content with CA1812 on. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…merCheck Root props adds CA1812 to NoWarn only when NuruConsumerCheck is not true, so the consumer check enables the rule without a NoWarn property function the suppression audit miscounts. Also set the executable bit on generator-73. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ernal-handler-classes-trip-ca1812-in
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
StevenTCramer
deleted the
task/573-devcli-internal-handler-classes-trip-ca1812-in
branch
November 13, 2026 20:17
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Reproduction
With CA1812 enabled in
tests/devcli-consumer-check, exactly four shipped content types fired,the four the description lists:
CheckVersionCommand.Handler,CleanCommand.Handler,ReleaseCommand.Handler,SelfInstallCommand.Handler. No service or other content type fired;the generator already builds the content services and commands with
new.Cause
The TimeWarp.Mediator generator registers each nested handler as
AddScoped<Handler>(services).The container builds it by reflection, so no
new Handler(...)appears in the compilation.Fix (generator, no change to the shipped content)
EndpointExtractor.IsFactoryConstructibleflags a nested[NuruRoute]Handler declared inthis compilation, not abstract or generic, with exactly one public constructor whose
parameters are all required (no default,
paramsorref). Model field:HandlerDefinition.NestedHandlerFactoryConstructible.interceptor-emitter.handler-factories.csemits__UseHandlerFactory<THandler>and, rightafter
AddGeneratedMediator(services)in both the source-gen mediator container and theruntime-DI container, one call per flagged handler:
__UseHandlerFactory<H>(services, static sp => new H(GetRequiredService<T1>(sp), ...)). Itreplaces the mediator's own descriptor with the same lifetime (it only swaps a non-keyed
descriptor whose implementation type is the handler, and adds nothing otherwise). That matches
how the container builds a single-constructor type, so dispatch does not change. Registrations
made later (a runtime-DI app's
ConfigureServices) still win. The explicitnewin thegenerated code is what CA1812 counts.
arguments) keep the reflection registration.
internal sealed class Handler(no CA1034), no pragma,[SuppressMessage]or<auto-generated/>. The consumer check also runs CA2000 and CA1034(AnalysisMode All, warnings as errors) and passes.
Regression gate
Directory.Build.propsadds CA1812 to NoWarn only whenNuruConsumerCheckis nottrue(same per-file suppression count).tests/devcli-consumer-check/Directory.Build.propssets
NuruConsumerCheck=truebefore its import, so the check (CI samples stage,workflow.yml"DevCli consumer check") compiles the content with CA1812 on.all four handlers; restored, it passes.
tests/timewarp-nuru-tests/generator/generator-73-nested-handler-factories.cs(Roslyn-hosted,standalone list + CiTestExcludes): factory emitted with resolved arguments, emitted after
AddGeneratedMediator, a zero-dependency handler usesstatic _, skipped for twoconstructors and for an optional argument, none without a generated mediator.
Gates
./bin/dev build: passed (0 warnings, 0 errors)../bin/dev test: passed (exit 0; 2403 PASSED, 0 FAILED; generator-73 4/4 in standalone).ganda repo audit:analyzer-suppressionsand every check this branch touches pass. Therun before the fix commit failed
runfile-executableon generator-73 (index lacked +x, fixedwith
git add --chmod=+x). It also reportedkanban-landedfor task 575, which is not thistask: 575 is a live
ganda task work-setwalk (intofeature/overnight-2026-11-14) whoseclaimed kitchen has not landed yet. That walk's host owns that kitchen, so this branch leaves it alone.
vscode-window-iconis a Warning (missing local.vscode/settings.json, ignored file), notblocking.
Test plan
Smoke:
Expect: the consumer check prints
Build succeeded.with no CA1812 (CA1812 is on there); thegenerated file has the helper plus four
__UseHandlerFactory<global::DevCli.*.Handler>linesafter
AddGeneratedMediator(services);; generator-73 passes 4/4; the check-version rundispatches through the factory-built handler and prints the version report (currently
"4.0.0-beta.13 was already released").
Kanban task 573
Session: b2020e9f-5c06-487a-a0b3-831ae1639f80