Verify the netstandard2.0 libraries on the .NET Framework 4.7.2 floor - #198
Merged
Conversation
The libraries target netstandard2.0 and were advertised as running on .NET Framework 4.6.1+, but 4.6.1 is only the theoretical minimum: the netstandard2.0 facades ship in-box from 4.7.2, and the claim was never verified in CI. Record 4.7.2 as the supported floor and correct the README to match. ADR-0022 refines the incidental 4.6.1 line in ADR-0002 (whose decision is the tooling floor, not the library one) without superseding it, and is recorded as Accepted per the maintainer's decision. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012UcTTqS7hwNHhgxdm8wQU4
netstandard2.0 is only a compile contract; running on the real .NET Framework CLR is what proves the libraries behave there. Add a gated net472 leg to the three test projects that cover the shipped libraries, wired through the shared build/Net472TestFloor.props. EnableNet472Floor keeps net472 out of the ordinary build and the local inner loop; only the opt-in CI job adds it. The leg needs LangVersion=latest (net472 defaults C# to 7.3, which rejects nullable), OutputType=Exe (xUnit v3 on .NET Framework), the reference-assembly pack to compile off-Windows, and an internal IsExternalInit polyfill for the records/init a few test models use. The shipped libraries use none of these and are untouched. The System.Text.Json round-trip test is excluded on net472 (a worker concern that never runs there); RequestBinder reaches the floor through its property tests, since its unit-test fixtures bind DateOnly (net6+). AsEnumerable().Reverse() pins the LINQ overload over the void MemoryExtensions.Reverse(Span) that wins once System.Memory is present. Two ErrorCode/ErrorContextKey blank-input tests pinned the exact ArgumentException.Message, whose parameter suffix .NET Framework renders as "...\nParameter name: x" where modern .NET uses "... (Parameter 'x')"; they now assert the message content and ParamName — the contract, stable on both. The library guards are unchanged. See ADR-0022. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012UcTTqS7hwNHhgxdm8wQU4
Add a Windows framework-floor job that runs the three net472-enabled test projects on .NET Framework 4.7.2 (EnableNet472Floor plus -f net472), proving the libraries load and pass on that runtime — the guarantee the Linux/net10 legs cannot give. A per-project loop keeps net472 off the net10-only projects a solution-wide -f would otherwise force it onto. Extend the weekly canary to run the library suites on the next .NET preview: the build stays on the .NET 10 SDK and only the test host rolls forward, so a runtime regression that breaks behaviour surfaces before that major ships. Best-effort and non-blocking, like the rest of the canary. See ADR-0022. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012UcTTqS7hwNHhgxdm8wQU4
Reefact
force-pushed
the
claude/dotnet-framework-47x-tests-qvx37f
branch
from
July 19, 2026 20:08
bf48811 to
1166132
Compare
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
The netstandard2.0 libraries were advertised as running on .NET Framework 4.6.1+, but that claim was never exercised in CI. This pins the honest, tested floor at 4.7.2 (the first .NET Framework that ships the netstandard2.0 facades in-box) and enforces it with a dedicated Windows CI job, so the support claim is verified on every pull request instead of merely asserted.
Type of change
Changes
net472leg to the three test projects that cover the shipped libraries (FirstClassErrors.UnitTests,FirstClassErrors.PropertyTests,FirstClassErrors.RequestBinder.PropertyTests), wired through a sharedbuild/Net472TestFloor.props. It is opt-in viaEnableNet472Floor, so the ordinary build and the local inner loop stay net10.0-only.LangVersion=latest(net472 defaults C# to 7.3, which rejects nullable),OutputType=Exe(xUnit v3 on .NET Framework), theMicrosoft.NETFramework.ReferenceAssembliespack (hermetic compilation off-Windows), and an internalIsExternalInitpolyfill for the records/init a few test models use. The shipped libraries use none of these and are untouched.System.Text.Jsonround-trip test on net472 (a worker-side concern that never runs there).RequestBinder.UnitTestsstays net10.0-only because its fixtures bindDateOnly(a .NET 6+ type absent from .NET Framework), so RequestBinder reaches the floor through its property tests. PinAsEnumerable().Reverse()so the LINQ overload wins over the voidMemoryExtensions.Reverse(Span<T>)onceSystem.Memoryenters the net472 graph.framework-floorCI job that runs the three legs on .NET Framework 4.7.2, and extend the weeklycanaryto run the library suites on the next .NET preview (best-effort, non-blocking).4.6.1+to4.7.2+.Testing
dotnet build FirstClassErrors.sln— clean (0 warnings, 0 errors).dotnet test FirstClassErrors.sln— 1070 tests pass on net10.0.FirstClassErrors.Analyzers.UnitTests) — 85, run as part of the solution test.Documentation
doc/updateddoc/handwritten/for-users/README.fr.md) updated if user-facing behavior changedADR-0022 is added in both English and French (the bilingual ADR convention). No user-facing behaviour changed in
README.fr.md; the only support claim lives in the NuGet README, which has no French counterpart.Architecture decisions
ADR-0022 refines the incidental "4.6.1" line in ADR-0002 without superseding it — ADR-0002's decision is the tooling floor, not the library one.
Related issues
None.
🤖 Generated with Claude Code
https://claude.ai/code/session_012UcTTqS7hwNHhgxdm8wQU4
Generated by Claude Code