What happened?
TransitiveClosureWalker.IsLoggingOwned (ADR-0055 Amendment 4) is supposed to make Compono.Logging the sole owner of ILogger/ILogger<T> when ComponoGeneratedLogging is enabled - excluding it from Compono.TestDoubles generation so there's exactly one Verify() extension. In practice this exclusion silently fails to apply when the consumer solution is built with MSBuild's default parallelism.
Reproduced in alexa-vox-craft (a real dogfood consumer) after bumping all Compono packages to the real, lockstep 1.0.0 NuGet.org release (Compono, Compono.XunitV3, Compono.Http, Compono.TestDoubles, Compono.Bogus, Compono.Logging all at 1.0.0) with a clean obj/bin and a clean NuGet restore - so this isn't a stale-cache or version-skew artifact.
With the default parallel build, AlexaVoxCraft.MediatR.Tests/Pipeline/PerformanceLoggingBehaviorTests.cs fails with 14 errors like:
error CS1061: 'Microsoft_Extensions_Logging_ILogger_global__AlexaVoxCraft_MediatR_Pipeline_PerformanceLoggingBehavior__bb9c11a6_DoubleVerifier' does not contain a definition for 'AtLevel' and no accessible extension method 'AtLevel' accepting a first argument of type '...DoubleVerifier' could be found
This is exactly the ownership collision ADR-0055 Amendment 4 exists to prevent: Compono.TestDoubles generated its own double + Verify()/...DoubleVerifier for ILogger<PerformanceLoggingBehavior> instead of yielding to Compono.Logging's Verify() (which returns LogVerificationBuilder with AtLevel).
Both ComponoGeneratedLogging and ComponoGeneratedTestDoubles resolve to true via -getProperty in this project, and the consumer's composition profile already registers UseLogging() before UseGeneratedTestDoubles() per the documented ordering guidance - so this isn't a consumer-side ordering mistake.
Consistently reproducible, not a flake: ran the default parallel dotnet build 3x from a clean obj/bin - failed all 3 times with the identical 14 errors. Ran dotnet build -m:1 (single MSBuild node) 2x from a clean obj/bin - succeeded both times, 0 errors.
Suspect area: LoggingWellKnownTypes.TryCreate's per-process BoundedCacheWithFactory<Compilation, LoggingWellKnownTypes?> (src/Compono.Generators/WellKnownTypes/BoundedCacheWithFactory.cs) - it's a size-5 bounded cache shared across the whole VBCSCompiler build-server process. Under the default parallel build, many projects/TFMs compile concurrently against that one shared generator instance; haven't nailed the exact mechanism, but that's the most likely place a Compilation-keyed lookup could go wrong/stale/get evicted in a way that causes IsLoggingOwned (src/Compono.Generators/Discovery/TransitiveClosureWalker.cs:190-218) to see a null/incorrect LoggingWellKnownTypes for a compilation that should have it.
Steps to reproduce
- In a consumer repo referencing
Compono, Compono.XunitV3, Compono.TestDoubles, Compono.Logging all pinned to 1.0.0 (lockstep) via Central Package Management, with a project that composes an ILogger<T> used both via UseLogging() (Compono.Logging capturing logger) and via generated test doubles elsewhere in the same project.
rm -rf every obj/bin in the solution, then dotnet restore.
dotnet build (default parallelism).
- Observe
CS1061 ... does not contain a definition for 'AtLevel' on the ILogger<T>.Verify() call sites.
rm -rf obj/bin again, then dotnet build -m:1.
- Build succeeds with 0 errors.
Environment
- .NET SDK targeting net8.0/net9.0/net10.0/net11.0 (multi-targeted test project)
- macOS (Darwin 25.6.0)
- Compono 1.0.0, Compono.XunitV3 1.0.0, Compono.TestDoubles 1.0.0, Compono.Logging 1.0.0 (all from nuget.org, Central Package Management)
- Consumer repo: LayeredCraft/alexa-vox-craft,
AlexaVoxCraft.MediatR.Tests project
What happened?
TransitiveClosureWalker.IsLoggingOwned(ADR-0055 Amendment 4) is supposed to make Compono.Logging the sole owner ofILogger/ILogger<T>whenComponoGeneratedLoggingis enabled - excluding it from Compono.TestDoubles generation so there's exactly oneVerify()extension. In practice this exclusion silently fails to apply when the consumer solution is built with MSBuild's default parallelism.Reproduced in
alexa-vox-craft(a real dogfood consumer) after bumping all Compono packages to the real, lockstep1.0.0NuGet.org release (Compono, Compono.XunitV3, Compono.Http, Compono.TestDoubles, Compono.Bogus, Compono.Logging all at1.0.0) with a cleanobj/binand a clean NuGet restore - so this isn't a stale-cache or version-skew artifact.With the default parallel build,
AlexaVoxCraft.MediatR.Tests/Pipeline/PerformanceLoggingBehaviorTests.csfails with 14 errors like:This is exactly the ownership collision ADR-0055 Amendment 4 exists to prevent: Compono.TestDoubles generated its own double +
Verify()/...DoubleVerifierforILogger<PerformanceLoggingBehavior>instead of yielding to Compono.Logging'sVerify()(which returnsLogVerificationBuilderwithAtLevel).Both
ComponoGeneratedLoggingandComponoGeneratedTestDoublesresolve totruevia-getPropertyin this project, and the consumer's composition profile already registersUseLogging()beforeUseGeneratedTestDoubles()per the documented ordering guidance - so this isn't a consumer-side ordering mistake.Consistently reproducible, not a flake: ran the default parallel
dotnet build3x from a cleanobj/bin- failed all 3 times with the identical 14 errors. Randotnet build -m:1(single MSBuild node) 2x from a cleanobj/bin- succeeded both times, 0 errors.Suspect area:
LoggingWellKnownTypes.TryCreate's per-processBoundedCacheWithFactory<Compilation, LoggingWellKnownTypes?>(src/Compono.Generators/WellKnownTypes/BoundedCacheWithFactory.cs) - it's a size-5 bounded cache shared across the whole VBCSCompiler build-server process. Under the default parallel build, many projects/TFMs compile concurrently against that one shared generator instance; haven't nailed the exact mechanism, but that's the most likely place aCompilation-keyed lookup could go wrong/stale/get evicted in a way that causesIsLoggingOwned(src/Compono.Generators/Discovery/TransitiveClosureWalker.cs:190-218) to see a null/incorrectLoggingWellKnownTypesfor a compilation that should have it.Steps to reproduce
Compono,Compono.XunitV3,Compono.TestDoubles,Compono.Loggingall pinned to1.0.0(lockstep) via Central Package Management, with a project that composes anILogger<T>used both viaUseLogging()(Compono.Logging capturing logger) and via generated test doubles elsewhere in the same project.rm -rfeveryobj/binin the solution, thendotnet restore.dotnet build(default parallelism).CS1061 ... does not contain a definition for 'AtLevel'on theILogger<T>.Verify()call sites.rm -rfobj/binagain, thendotnet build -m:1.Environment
AlexaVoxCraft.MediatR.Testsproject