Skip to content

OSPO readiness: defect ledger, multi-targeting, and preview validation - #53

Merged
Digvijay merged 38 commits into
mainfrom
ospo-readiness
Sep 26, 2026
Merged

Digvijay merged 38 commits into
mainfrom
ospo-readiness

Conversation

@Digvijay

Copy link
Copy Markdown
Owner

Prepares this repository for a Microsoft OSPO conversation, alongside four sibling libraries and the viking-air integration demo.

What is here

  • Governance and OSPO hygiene files.
  • Multi-targeting net8.0 (LTS) and net10.0 (current), with an opt-in net11.0 leg in CI so next year's breaking changes surface during the preview window rather than on release day.
  • Every defect found during the review recorded in docs/known-issues.md with its root cause, and each fix pinned by a test or build check that fails without it.

Why the ledger is in the repository

Entries are kept after they are resolved, so anyone evaluating a specific released version can see what applied to it. Where something is not fully fixed, it says so and says why.

Evidence

Built and tested locally on SDK 10.0.401 and 11.0.100-rc.1.26425.128 on Windows ARM64, with zero build warnings. This pull request exists partly so CI runs it on x64 and Linux, which has never happened.

dependabot Bot and others added 30 commits February 26, 2026 06:20
---
updated-dependencies:
- dependency-name: Microsoft.Extensions.Hosting
  dependency-version: 10.0.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
---
updated-dependencies:
- dependency-name: Microsoft.NET.Test.Sdk
  dependency-version: 18.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 4 to 6.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](actions/setup-node@v4...v6)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 6 to 7.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v6...v7)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [actions/upload-pages-artifact](https://github.com/actions/upload-pages-artifact) from 3 to 4.
- [Release notes](https://github.com/actions/upload-pages-artifact/releases)
- [Commits](actions/upload-pages-artifact@v3...v4)

---
updated-dependencies:
- dependency-name: actions/upload-pages-artifact
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps Microsoft.CodeAnalysis.Analyzers from 3.11.0 to 5.3.0-2.25625.1
Bumps Microsoft.CodeAnalysis.CSharp from 5.0.0 to 5.3.0

---
updated-dependencies:
- dependency-name: Microsoft.CodeAnalysis.Analyzers
  dependency-version: 5.3.0-2.25625.1
  dependency-type: direct:production
  update-type: version-update:semver-major
- dependency-name: Microsoft.CodeAnalysis.CSharp
  dependency-version: 5.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
updated-dependencies:
- dependency-name: Microsoft.Extensions.Caching.Hybrid
  dependency-version: 10.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
updated-dependencies:
- dependency-name: coverlet.collector
  dependency-version: 8.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
---
updated-dependencies:
- dependency-name: FluentAssertions
  dependency-version: 8.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
updated-dependencies:
- dependency-name: Microsoft.AspNetCore.OpenApi
  dependency-version: 10.0.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
---
updated-dependencies:
- dependency-name: Microsoft.Extensions.DependencyInjection
  dependency-version: 10.0.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
---
updated-dependencies:
- dependency-name: Microsoft.SourceLink.GitHub
  dependency-version: 10.0.201
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
---
updated-dependencies:
- dependency-name: System.Text.Json
  dependency-version: 10.0.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [actions/deploy-pages](https://github.com/actions/deploy-pages) from 4 to 5.
- [Release notes](https://github.com/actions/deploy-pages/releases)
- [Commits](actions/deploy-pages@v4...v5)

---
updated-dependencies:
- dependency-name: actions/deploy-pages
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
- Add CODE_OF_CONDUCT.md, SECURITY.md, SUPPORT.md, CODEOWNERS, dependabot,
  issue and PR templates, and OSPO compliance and AOT validation workflows.
- Add docs/dependency-exceptions.md for recording time-bound advisory
  exceptions rather than suppressing the audit.
- Remove a stray analysis.json produced by a binlog analysis tool, and ignore
  it and *.binlog going forward.
- Extend .gitignore for *.snupkg and *.backup.

Rapp was the one library in this portfolio that produced no defects during the
viking-air integration: binary caching and the schema guard behaved exactly as
documented, including under Native AOT.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a0724329-1de1-4f2f-979e-358df948bd49
Rapp.Tests declared no target framework, so it inherited the singular
TargetFramework property from Directory.Build.props. That property
silently defeats each project's plural TargetFrameworks, so the net8.0
target framework was built and published without a single test ever
having run on it. Removing the global property and adopting the shared
toolkit policy took the suite from 88 tests to 176 without one new test
being written.

Pins Microsoft.OpenApi to a patched version and pins AnalysisLevel to
10.0, so that installing a newer SDK cannot fail an unchanged build.

Verified: 176 tests on net8.0 and net10.0, 88 on .NET 11 RC1.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a0724329-1de1-4f2f-979e-358df948bd49
The counts in the submission pack did not reconcile with the repositories' own known-issues files, and Rapp had no such file at all while being credited with three fixed defects. Recounted from the files rather than from the summary.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a0724329-1de1-4f2f-979e-358df948bd49
RappGenerator carried an INamedTypeSymbol through the incremental pipeline and
RappGhostGenerator a ClassDeclarationSyntax. Neither is equatable across
compilations, so nothing was ever cached: code generation re-ran for every
[RappCache] and [RappGhost] type on every keystroke, and each cached step held
the previous compilation alive. Both now use ForAttributeWithMetadataName and
project into equatable value models. ImmutableArray<T> compares by the identity
of its underlying array, so EquatableArray<T> is needed too, and a
netstandard2.0 generator needs an IsExternalInit polyfill before it can declare
records at all. Generated output is unchanged.

GeneratorIncrementalityTests runs each generator against two separately built
but identical compilations and asserts every tracked step reports Cached or
Unchanged. It includes a deliberately defective symbol-carrying generator as a
control, so the harness is known to be able to fail rather than merely observed
to pass.

The samples' JSON size comparison, orphaned when the library-side measurement
was removed, comes back as Rapp.Dashboard.RappSizeComparison: opt-in, called
from the samples' own cache-miss paths, annotated for trimming and AOT with a
JsonTypeInfo overload for callers who need to stay Native-AOT-safe. It was
deliberately not restored to the library. TelemetryOverheadTests listens to the
Rapp meter over a hundred round trips and asserts no size measurement is
emitted; built with -p:DefineConstants=RAPP_TELEMETRY it fails with 400 of them.
The listener filters by calling thread, because a MeterListener is
process-global and RappMetricsTests exercises RecordSerializationSize on a
parallel xUnit thread.

Two findings came out of this work rather than being planned:

The three sample projects were referenced only by Samples/Rapp.Samples.sln. CI
built Rapp.sln, so the repository's only demonstration of how the library is
meant to be used had never been compiled by any pipeline. Building them raised
CA1873 twice in the gRPC sample immediately. They are now in Rapp.sln, so
TreatWarningsAsErrors covers them, and the logging is [LoggerMessage]-generated.
This is the third time in this review that a project outside the build graph
turned out to be outside the audit.

Six project files appended RAPP_TELEMETRY to DefineConstants. A #if is evaluated
where the code containing it is compiled, and every #if RAPP_TELEMETRY block is
in Rapp's own sources, so none of the six changed a byte of output while
implying the cost was opt-in. That misunderstanding is exactly what the
double-serialization defect was. Removed.

Verified: Rapp.sln builds with 0 warnings and 0 errors, and 95 tests pass on
each of net8.0, net10.0 and net11.0 (SDK 11.0.100-rc.1.26425.128).

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a0724329-1de1-4f2f-979e-358df948bd49
The AOT validation workflow had never completed a run. -p:PublishAot=true on
the command line is a global property, which MSBuild propagates into every
ProjectReference, including Rapp.Gen -- netstandard2.0, which cannot be
AOT-compiled (NETSDK1207). The flag was redundant; the project declares it.

The thirteen IL warning codes were passed comma-separated, and the dotnet CLI
splits -p: values on commas, so the run died with MSB1006 before compiling
anything. The workflow that was the evidence for Rapp being trim- and AOT-clean
had never enforced a single one of those warnings.

Publishing a multi-targeted project also needs an explicit --framework
(NETSDK1129), passed on the publish step only.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a0724329-1de1-4f2f-979e-358df948bd49
Once the workflow was fixed enough to run, it failed - on MemoryPack and
HybridCache, not on Rapp. It published a sample with TreatWarningsAsErrors
and TrimmerSingleWarn=false, which makes every trim warning in the whole
program fatal and cannot distinguish "Rapp is AOT-safe" from "everything
Rapp depends on is AOT-safe". The second is not true.

Measured with .NET 10.0.12 ILC: 21 warnings from MemoryPack 1.21.4's
reflective formatter provider, 9 from Caching.Hybrid 10.3.0's JSON
fallback, and 0 from Rapp.

The easy repair is NoWarn. It was rejected: warning codes are not owned by
an assembly, so NoWarn=IL3050 silences Rapp as well as MemoryPack, and the
gate would pass by construction. There are no IL suppressions here.

Instead tools/Rapp.AotProbe consumes only the public package surface. CI
publishes it with PublishAot=true, leaves ILC warnings non-fatal so that
compilation completes, and fails if any warning names a Rapp type. That
says exactly what the README claims and cannot be weakened by adding a
code to a list. Verified both ways: it passes on the real code, and it
caught all three warnings from a MakeGenericType call temporarily added to
src/Rapp.

Leaving the warnings non-fatal also means the native binary gets built, so
CI runs it. Compiling shows only that ILC was willing to compile; running
is what shows the reflective fallbacks are unreachable, because under
Native AOT a reached fallback throws rather than degrading quietly.

The README overstated this. It claimed "100% compatible with Native AOT"
and that Rapp avoided reflection "preventing AOT trim warnings", when a
consumer setting PublishAot=true sees 30. It now states what is verified,
and documents the case that actually bites: a type cached without
[RappCache] falls back to reflection-based System.Text.Json, which is not
AOT-safe. Also fixes a duplicated heading and an unterminated code fence.

The blocking analyzer job is re-scoped from Rapp.sln to src/Rapp; the
samples become advisory.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a0724329-1de1-4f2f-979e-358df948bd49
Bring the hardened build, multi-target test matrix, defect ledger, and Native AOT validation gate onto main before taking the Dependabot queue. This establishes the warning-as-error and AOT baseline that the dependency updates must preserve.

Verified previously on pull request #53 with CI, OSPO compliance, and the AOT probe green on Ubuntu and Windows.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a0724329-1de1-4f2f-979e-358df948bd49
Take Dependabot's System.Text.Json patch update after the OSPO baseline so the generator and samples are tested against the patched serializer runtime.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a0724329-1de1-4f2f-979e-358df948bd49
Take Dependabot's SourceLink patch branch into history while preserving the OSPO cleanup that removed the redundant package reference from the build.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a0724329-1de1-4f2f-979e-358df948bd49
Update the dependency injection package used by Rapp's samples, tests, and AOT probe to the latest patch train before validating the full solution.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a0724329-1de1-4f2f-979e-358df948bd49
Update the OpenAPI package used by the playground while keeping the explicit Microsoft.OpenApi vulnerability pin until restore proves it is unnecessary.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a0724329-1de1-4f2f-979e-358df948bd49
Update the assertion library used by the net8.0 and net10.0 test suite without changing test semantics.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a0724329-1de1-4f2f-979e-358df948bd49
Update the test coverage collector patch version while preserving the existing xUnit test coverage configuration.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a0724329-1de1-4f2f-979e-358df948bd49
Update the test SDK before running the full multi-target test suite so test discovery remains covered by local validation and CI.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a0724329-1de1-4f2f-979e-358df948bd49
Update the hosting package used by benchmark infrastructure while keeping the OSPO warning-as-error baseline intact.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a0724329-1de1-4f2f-979e-358df948bd49
Update Microsoft.CodeAnalysis.CSharp and Microsoft.CodeAnalysis.Analyzers together so the generator is checked against the current Roslyn 5 patch train. This merge is intentionally isolated because new analyzer rules are treated as product findings under the OSPO warning-as-error baseline.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a0724329-1de1-4f2f-979e-358df948bd49
Digvijay Chauhan and others added 8 commits September 26, 2026 14:53
Update HybridCache on its own because the AOT probe exercises this dependency directly. The merge keeps the origin-based Native AOT gate intact so CI must prove Rapp still contributes no trim or AOT warnings.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a0724329-1de1-4f2f-979e-358df948bd49
Update artifact uploads after checking every workflow use. Artifact names remain unique across matrices and no direct-upload or overwrite behavior is used, so the v7 artifact semantics do not require workflow restructuring.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a0724329-1de1-4f2f-979e-358df948bd49
Update the docs build to setup-node 6 after checking the VitePress workflow. It pins Node 20, does not use setup-node caching, and the docs package has no packageManager field, so the v5/v6 caching changes do not alter this build.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a0724329-1de1-4f2f-979e-358df948bd49
Update the Pages artifact upload after checking the VitePress output path. The workflow uploads docs/.vitepress/dist as one Pages artifact and does not rely on hidden dotfiles, so the v4 dotfile exclusion does not require an input change.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a0724329-1de1-4f2f-979e-358df948bd49
Update the Pages deployment action after checking compatibility with the paired upload-pages-artifact step. The workflow already grants pages and id-token permissions and now uploads with upload-pages-artifact 4, which remains compatible with deploy-pages 5.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a0724329-1de1-4f2f-979e-358df948bd49
Document the package and workflow action updates that were merged after the OSPO baseline, including the isolated Roslyn and HybridCache bumps that required extra validation.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a0724329-1de1-4f2f-979e-358df948bd49
The repository ruleset requires CodeQL code scanning results on the exact pull request head commit. The previous synchronize event produced all build, OSPO, benchmark, and AOT checks but left code scanning waiting, so this empty commit retriggers validation without changing the tree.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a0724329-1de1-4f2f-979e-358df948bd49
The existing CodeQL workflow is disabled by repository inactivity and cannot be re-enabled through this account. Add an active equivalent workflow so the repository ruleset can receive CodeQL code scanning results for the PR head commit before merge.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a0724329-1de1-4f2f-979e-358df948bd49
Comment on lines +49 to +51
(CSharpGeneratorDriver)CSharpGeneratorDriver.Create(
new ISourceGenerator[] { new RappGenerator().AsSourceGenerator(), new RappGhostGenerator().AsSourceGenerator() },
driverOptions: new GeneratorDriverOptions(IncrementalGeneratorOutputKind.None, trackIncrementalGeneratorSteps: true));
Comment on lines +130 to +132
var driver = (CSharpGeneratorDriver)CSharpGeneratorDriver.Create(
new ISourceGenerator[] { new SymbolCarryingGenerator().AsSourceGenerator() },
driverOptions: new GeneratorDriverOptions(IncrementalGeneratorOutputKind.None, trackIncrementalGeneratorSteps: true));
((string)AppContext.GetData("TRUSTED_PLATFORM_ASSEMBLIES")!)
.Split(Path.PathSeparator)
.Select(p => MetadataReference.CreateFromFile(p))
.Append(MetadataReference.CreateFromFile(Path.Combine(AppContext.BaseDirectory, "Rapp.dll"))),
@Digvijay
Digvijay merged commit 46a7386 into main Sep 26, 2026
13 checks passed
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.

2 participants