Skip to content

chore: move hosts and shipped artifacts to .NET 10 LTS (SDK 10.0.1xx) [D4 assumed, CI-verified only] - #340

Merged
IanFrelinger merged 9 commits into
masterfrom
chore/net10-lts
Aug 17, 2026
Merged

chore: move hosts and shipped artifacts to .NET 10 LTS (SDK 10.0.1xx) [D4 assumed, CI-verified only]#340
IanFrelinger merged 9 commits into
masterfrom
chore/net10-lts

Conversation

@IanFrelinger

@IanFrelingerIanFrelinger commented Aug 17, 2026

Copy link
Copy Markdown
Owner

DRAFT. Merging this requires .NET 10 SDK on developer machines and the owner's D4 confirmation.
Local box has SDK 9 only and no Docker: this PR is CI-verified only (see the CI state section at the end).

[skip-prod-style] Rationale: no production wiring changes. The production-path diffs are TFM/TargetFrameworks edits in .csproj files, an XML-doc/sdk: image string in Nexo.Infrastructure (session build TFM), and two SYSLIB0057 obsoletion shims with unchanged behaviour; the ProdStyle / virtual-host suites themselves move to net10.0 and run in the mcp-a2a-gate / distribution-matrix-gate lanes on this PR.

Why

.NET 9 (STS) left support May 2026; .NET 8 LTS ends Nov 2026; .NET 10 LTS shipped Nov 2025. The repo pinned SDK 9.0.100, shipped net8.0 hosts on aspnet:8.0, and ran the in-process API tests on net9.

What

  • global.json -> 10.0.100, rollForward: latestFeature. C# 12 LangVersion pin kept (rationale still holds on the C# 14 compiler).
  • Hosts / shipped executables -> net10.0: Nexo.CLI, Nexo.Mcp.Server.Host, Nexo.Transport.Grpc.Server.Host, ValidationUtilities, tools/*, first-flight spike; Nexo.Tests.CLI follows the CLI.
  • Libraries -> net8.0;net10.0; netstandard2.0 contracts -> netstandard2.0;net8.0;net10.0 (Brick.Contracts keeps net8.0 for generated bricks). Test projects net8.0;net9.0 -> net8.0;net10.0; VirtualProduction / A2A TestServer suites are net10-only with Mvc.Testing/TestHostVersionOverride=10.0.11.
  • Nexo.API multi-targets net8.0;net10.0 (not net10-only): consumed as a library by the net8.0 inner build of Nexo.Tests.Infrastructure (Tests/API/**) and by the commercial hosts (out of scope). Images publish -f net10.0; every dotnet run --project application/src/Nexo.API in scripts/docs now passes -f net10.0.
  • Dockerfiles: sdk:10.0 / aspnet:10.0; agent-server drops its 8.0 runtime install; test images build -f net10.0 and keep the 8.0 runtime only for the net8.0 test hosts; fleet-host/game-director keep an 8.0 runtime stage for the commercial net8.0 hosts.
  • Dev container / bootstrap / setup scripts: devcontainers/dotnet:10.0-noble, sdk:10.0 (+ sdk:10.0-noble where a second distro was probed - MCR publishes no Debian -bookworm-slim/-trixie-slim for sdk:10.0), setup scripts require SDK >= 10 and install channel 10.0 / Microsoft.DotNet.SDK.10.
  • Session candidate build / execution runner generate net10.0 projects and the spike pins sdk:10.0 (a net10.0 host streaming its reference assemblies into a net9.0 candidate would fail with CS1705).
  • Workflows: 9.0.x -> 10.0.x everywhere; 8.0.x-only lanes now install 10.0.x explicitly (they only built because the runner image carried SDK 9); 8.0.x kept only where a lane deliberately exercises net8.0 outputs (cert-gate -f net8.0, gate scripts, consumer/sample lanes, single-target net8.0 test projects); CLI-only lanes and the full-platform-readiness native lane are 10.0.x only. -f net9.0 -> -f net10.0; container matrices pass DOTNET_VERSION=10.0.
  • Two SYSLIB0057 obsoletions surfaced by the net10 inner builds handled minimally (X509CertificateLoader under NET9_0_OR_GREATER for DER bytes; pragma + comment for the auto-detecting file-path loader in the gRPC channel factory).
  • Docs: README badge/prereqs, GettingStarted, CONTRIBUTING, IntegratorGuide matrix, DotnetVersions.md, gate/testing docs.

Skipped on inspection (with evidence)

  • Directory.Packages.props ASP.NET pins stay 8.0.0 (Mvc.Testing, TestHost, OpenApi, JwtBearer, OpenIdConnect): Mvc.Testing is referenced by commercial net8.0 test projects and by the net8.0 inner build of Nexo.Tests.Infrastructure; a 10.0.x central pin cannot resolve for net8.0. net10 consumers already use VersionOverride=10.0.11. The other three are unreferenced.
  • Nexo.BackgroundAgents.HostRunners is a library (no OutputType; referenced by Nexo.API's net8.0 build and Nexo.Tests.BackgroundAgents), so it multi-targets like the other libraries rather than going net10-only.
  • docs/TesterQuickstart.md does not exist on origin/master; not created here.
  • commercial/ untouched (explicit net8.0 TFMs, no shared property).

Grep survivors (justified)

  • .docker/Dockerfile.fleet-hostaspnet:8.0 runtime stage and Dockerfile.game-director 8.0 runtime install: commercial net8.0 hosts.
  • Directory.Build.props comment mentions net9.0 (LangVersion rationale); .docker/Dockerfile.agent-server, cross-platform-tests.yml, ValidationServiceAdapter.cs comments are historical.
  • ValidationServiceAdapterGapCoverageTestsnet9.0 strings are parser test data (generic TFM strings).
  • 8.0.x setup-dotnet entries and -f net8.0 gate scripts: deliberate net8 consumer lanes on multi-target suites.
  • Samples / docs demos / templates / spikes/portability stay net8.0 (consumer story).

Verification

  • XML well-formedness: all 124 *.csproj/*.props/*.targets load with System.Xml.XmlDocument; the WIP had left an invalid -- inside a comment in Nexo.API.csproj (fixed).
  • Survivor grep for net9.0|9.0.x|sdk:9.0|aspnet:8.0|SDK 9|channel 9.0 over non-md files: only the justified list above.
  • CI: see the CI state section below.

CI state (final head c088bbf5)

Four CI cycles were needed after the initial push (each was a real SDK-10 behaviour surfaced by CI, fixed minimally, one commit each):

  1. 7b5cfe46 - restore failed everywhere: NU1510 (SDK 10 package pruning warns on the audit-override direct references / 10.0.x pins; suppressed via NoWarn, pruning stays on) and NU1903 SSH.NET 2025.1.0 (SDK 10 audits transitive packages; Testcontainers consumers now reference SSH.NET 2026.0.0).
  2. d6f7ac1d - CA2024 (.NET 10 analyzer: StreamReader.EndOfStream in an async method) in OllamaHttpChatClient; loop now reads to null.
  3. 252e4ec1 - dotnet new sln defaults to .slnx on SDK 10; the external-product-shape script asks for --format sln.
  4. c088bbf5 - the Nexo.Tests.CLI public-API snapshots embed the assembly TargetFramework attribute; re-approved for v10.0 (1/2967 tests, surfaced by the full-platform-readiness Linux native lane).

Green on c088bbf5 (pull_request): Cert gate, Kernel Gate, Kernel coverage gate, Application Gate, Security Gate, Distribution Matrix Gate (CLI/API images on sdk:10.0/aspnet:10.0, in-process Nexo.API on net10, external product shape, standalone brick scaffold, StableSdkHostSample pack), Core domain coverage, Provenance Graph CI, Testing strategy gate, dependency-boundary, layer-boundary, Docs Link Check, Shell lint.
Green on c088bbf5 (dispatched): Full Platform Readiness Gate - all 11 jobs (Linux/macOS/Windows native on SDK 10 only, Ubuntu/Alpine/Debian containers, Docker CLI/API/agent-server/quickstart images).
Green on 252e4ec1 (dispatched; unchanged by the last commit, which only touched three snapshot files): MCP + A2A protocol gate (net10 TestServer suites), Dev Container Gate (devcontainers/dotnet:10.0-noble), Environment Setup Gate v1 (ubuntu/macos/windows + ephemeral sdk:10.0 and sdk:10.0-noble), Production Readiness Gate v1 (3 OSes, -f net8.0 + -f net10.0 pipeline lanes), Container Image Gate, onboarding-quickstart-gate.
Not run here: self-hosted / manual lanes (test-caching-multi-env, test-trust-multi-env, test-persistence-multi-os, cross-platform-tests, release lanes) - edited mechanically (9.0.x -> 10.0.x, -f net9.0 -> -f net10.0, DOTNET_VERSION=10.0); nothing red remains on the lanes that ran.

PlzTouchGrassand others added 7 commits August 16, 2026 23:42
Why: .NET 9 (STS) left support in May 2026 and .NET 8 LTS ends in
November 2026; .NET 10 is the current LTS. The repo still pinned SDK
9.0.100, shipped net8.0 hosts and images on aspnet:8.0, and ran the
net9-only in-process API tests on a framework that is out of support.
What changes (D4 assumed - owner to confirm):
- global.json pins sdk 10.0.100 (rollForward latestFeature). The C# 12
LangVersion pin stays; its rationale (OverloadResolutionPriority vs
FluentAssertions 8) holds for the C# 14 compiler too.
- Hosts and shipped executables (Nexo.CLI, Nexo.Mcp.Server.Host,
Nexo.Transport.Grpc.Server.Host, ValidationUtilities, tools/*, the
first-flight spike) target net10.0. Nexo.Tests.CLI follows the CLI.
- Libraries multi-target net8.0;net10.0 so the net8 consumer story stays
alive until Nov 2026; netstandard2.0 contracts become
netstandard2.0;net8.0;net10.0 (Brick.Contracts keeps net8.0 for the
generated bricks). Test projects move net8.0;net9.0 -> net8.0;net10.0;
the VirtualProduction / A2A TestServer suites are net10.0-only with the
10.0.11 Mvc.Testing / TestHost override.
- Nexo.API multi-targets net8.0;net10.0 rather than net10.0-only: it is
consumed as a library by the net8.0 inner build of
Nexo.Tests.Infrastructure (Tests/API) and by the commercial hosts
(out of scope). The images publish -f net10.0 and every
`dotnet run --project application/src/Nexo.API` now passes -f net10.0.
- Nexo.BackgroundAgents.HostRunners is a library (no OutputType), so it
multi-targets like the other libraries instead of net10.0-only.
- Dockerfiles: sdk:10.0 / aspnet:10.0; agent-server no longer installs
the 8.0 runtime; the test images build the net10.0 inner builds and
keep the 8.0 runtime only for the net8.0 test hosts. fleet-host and
game-director keep an 8.0 runtime stage for the commercial net8.0 hosts.
- Dev container / container bootstrap / setup scripts / verify matrix
move to the 10.0 images (sdk:10.0-noble replaces 9.0-bookworm-slim:
MCR publishes no Debian variant for sdk:10.0) and require SDK 10.
- Session candidate build / execution runner (SessionCandidateBuild,
SessionExecutionBackend) generate net10.0 projects: reference
assemblies streamed from a net10.0 host cannot compile against net9.0
(CS1705), so the in-session TFM has to follow the host TFM.
- Gate scripts that ran Nexo.Tests.CLI with -f net8.0 use -f net10.0;
scripts running the multi-target suites keep -f net8.0 on purpose.
- Two SYSLIB0057 obsoletions surfaced by the net10.0 inner builds are
handled minimally: DER bytes go through X509CertificateLoader on
NET9_0_OR_GREATER; the file-path loader in the gRPC channel factory is
kept (it is the only auto-detecting PFX/DER/PEM loader) under a pragma.
Skipped on inspection: Directory.Packages.props ASP.NET pins stay at
8.0.0 because net8.0 consumers (net8 inner builds, commercial tests)
still resolve them; the net10.0 consumers already use VersionOverride.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Why: global.json now pins SDK 10, so every setup-dotnet block that named
9.0.x moves to 10.0.x, and the lanes that only named 8.0.x (they built
because the runner image happened to carry SDK 9) now install 10.0.x
explicitly instead of depending on the image contents.
8.0.x stays only where a lane deliberately exercises the net8.0 outputs
(cert-gate and the gate scripts run the multi-target suites -f net8.0;
consumer/sample lanes build net8.0 consumers; single-target net8.0 test
projects). CLI-only lanes (runtime-release-*, runtime-studio-forge-smoke,
workflow-regression-gate) are 10.0.x only, and the full-platform-readiness
native lane stays SDK-single at 10.0.x per wave 1.
`-f net9.0` becomes `-f net10.0` (kernel-coverage, mcp-a2a, distribution
matrix, production readiness, trust multi-env, readiness containers), the
container matrices pass DOTNET_VERSION=10.0, and the ephemeral setup gate
uses sdk:10.0 / sdk:10.0-noble (no Debian variant exists for sdk:10.0).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Why: README badge, prerequisites, GettingStarted, CONTRIBUTING, the
IntegratorGuide compatibility matrix and DotnetVersions.md all said
SDK 9 / net8.0 hosts. They now describe SDK 10 (LTS), net10.0 hosts,
net8.0;net10.0 libraries, and the -f net10.0 needed to `dotnet run`
the multi-targeted Nexo.API. Gate/testing docs that mirror workflow
steps follow the workflow edits.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… restore
Why: the first CI cycle on SDK 10 failed at restore everywhere.
- NU1510 ("PackageReference X will not be pruned") is raised for the
audit-override references Directory.Build.props adds to every project
and for the 10.0.x central pins whenever the SDK's bundled runtime is
at least that patch - a condition that flips per SDK release. Suppress
the hint; pruning stays on.
- SDK 10 audits transitive packages by default, which surfaced SSH.NET
2025.1.0 (GHSA-q939-rpr3-3284) under Testcontainers. Both consumers
reference the patched 2026.0.0 directly (repo pattern for NU1903).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ndOfStream (CA2024)
Why: the .NET 10 analyzers (AnalysisLevel=latest under SDK 10) flag
StreamReader.EndOfStream inside async methods as CA2024, which is an
error under TreatWarningsAsErrors and blocked every lane in CI cycle 2.
ReadLineAsync returning null is the async end-of-stream signal; behaviour
is unchanged.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…defaults to .slnx)
Why: the external-product-shape lane creates a consumer solution and then
adds projects to ExternalProduct.sln; on SDK 10 'dotnet new sln' writes
ExternalProduct.slnx by default, so the follow-up 'dotnet sln add' could
not find the file. --format sln restores the previous behaviour.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Why: Nexo.Tests.CLI now targets net10.0 (it follows Nexo.CLI), so
PublicApiGenerator reads the net10.0 build of Nexo.Authoring / Nexo.Sdk /
Nexo.Framework.Sdk and the assembly-level TargetFramework attribute in the
approved snapshots is v10.0 instead of v8.0. Only that line changes; the
public surface itself is identical (full-platform-readiness Linux lane,
1/2967 tests).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@IanFrelinger
IanFrelinger marked this pull request as ready for review August 17, 2026 14:08
…ons, keep 10.0.x setup-dotnet, Orchestration csproj from this branch (master side was renormalization only)
…tatements updated to 10 (GettingStarted, IntegratorGuide, TesterQuickstart)
@IanFrelinger
IanFrelinger merged commit 61b1de9 into masterAug 17, 2026
17 of 19 checks passed
@IanFrelinger
IanFrelinger deleted the chore/net10-lts branch August 17, 2026 14:44
Sign up for freeto 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

@IanFrelinger@PlzTouchGrass