Visitar URL original
Select the .NET SDK Line in global.json and Tie the C# Version to the TFM by ptr727 · Pull Request #4109 · ptr727/ProjectTemplate · GitHub
Skip to content

Select the .NET SDK Line in global.json and Tie the C# Version to the TFM - #4109

Merged
ptr727 merged 10 commits into
developfrom
feature/dotnet-sdk-line-global-json
Nov 12, 2026
Merged

ptr727 merged 10 commits into
developfrom
feature/dotnet-sdk-line-global-json

Conversation

@ptr727

@ptr727 ptr727 commented Nov 12, 2026 •

Copy link
Copy Markdown
Owner

Summary

Implements the hub side of #4103. Every fleet .NET repo selects its SDK line in global.json, and the C# version follows the TFM rather than the installed compiler.

  • dotnet-codestyle Skill, "Central build and package configuration":
    • global.json is required, with an sdk block (10.0.100, rollForward: latestFeature, allowPrerelease: false). The test runner key appears only where the test project is MTP-based.
    • LangVersion is left unset in props files and in every project targeting a .NET TFM. A netstandard analyzer or source-generator project may set a fixed number, since unset it compiles at C# 7.3, which Nullable enable refuses.
    • latest, latestMajor, and preview are banned everywhere. AnalysisLevel stays latest-all.
    • The skill states the host requirement and the drift conditions, and says a major move starts in the hub's setup-dotnet steps.
  • references/testing.md and references/project-config.md point at that rule.
  • CODESTYLE.md .NET summary names the rule, so the new check's intentRef lands on it.
  • Audit: a new csharp.sdk.globaljson letter check in spec/project-types.json, and global.json in the csharp type's requiredFiles.
  • Baseline: a hub snippet catalog/snippets/configs/global.json (the sdk block only) and its spec/files.json entry, so standup and the presence audit carry the file.
  • The generated .github/skills/ and .claude-plugin/ copies are regenerated.

Follow-ups filed rather than done here: #4106 (the Linux installer installs only the newest SDK line by default) and #4107 (the hub's setup-dotnet steps read global.json once every .NET repo carries it).

The shape matches what the PhotoCleaner #262 change verified under SDK 10.0.404 and 11.0.100.

Part of #4103. The closing keyword belongs on the develop -> main promotion.

Open Findings From the Local Pass

  • .agents/skills/dotnet-codestyle/SKILL.md:121 (introduced): the netstandard exception sits between "Those float with the installed SDK's compiler." and the IDE0028/CS8652 sentence that explains it. That sentence then reads as a result of the fixed number. The edit budget was spent, so it was fixed in this pull request's review loop, in 9fd565e, with its own recorded pass (no findings).

  • spec/project-types.json:9 (introduced), raised by the local pass on b953e56: the csharp type's requiredFiles lists only .editorconfig and .gitattributes, while the new check makes a root global.json required for every C# repo. That push's edit budget was spent, so it was fixed in the next push (requiredFiles, then the snippet and baseline entry below).

Declined Findings From the Local Pass

  • A multi-targeting library (netstandard2.0;net10.0, or net8.0;net10.0), or a netstandard library that is not an analyzer, has no LangVersion instruction it can follow. Declined under GOVERNANCE.md "Trust Boundaries and Hardening Effort": no fleet repo multi-targets, and the only netstandard project in the fleet is an analyzer. A repo that adds one is the moment to extend the rule.

Review Follow-Ups

  • The Copilot finding on the LangVersion scope was fixed in 0d54f2f. The local pass on that fix also tightened the check: the version must be the 100 band, a global.json with no sdk block is drift, and the check's sentences were shortened.

  • A TFM major move keeps the old SDK line installed in the hub's steps until every repo has moved (b953e56). That ordering point is also noted on Read the .NET SDK Line From global.json in the Hub's setup-dotnet Steps #4107.

  • The local passes on the follow-up pushes also made the version exactly <major>.0.100 rather than any 1xx band, scoped the LangVersion rule to files the repo holds (the SDK's own targets set it), banned EnablePreviewFeatures, named the devcontainer image as a second SDK-line site, and moved a netstandard project's fixed LangVersion with the TFM. The last pass on the head found nothing.

Verification

  • scripts/build_dist.py --check: generated skill distributions are current.
  • scripts/prose_lint.py --diff origin/develop: no violations.
  • spec/validate.py: OK.
  • markdownlint-cli2 on the changed Markdown: 0 issues.
  • Full pytest tests/ on the head: 4009 passed, 11 skipped.
  • scripts/repo_gate.py: all checks ok.
  • Four recorded local-strict-review passes: six findings fixed in round one, one in round two, one listed above and fixed, and a clean pass on that fix.

🤖 Generated with Claude Code

ptr727 and others added 3 commits November 12, 2026 10:17
… TFM

Require a root global.json sdk block (version 10.0.100, rollForward
latestFeature) in every .NET repo, leave LangVersion unset so the C#
version follows the TFM, and add the csharp.sdk.globaljson audit check.

Closes #4103

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Answer the local strict review: state why allowPrerelease is false and
audit it, scope the test runner key to MTP repos, tie the sdk major to
the .NET TFM rather than a netstandard one, say a major move starts in
the hub's setup-dotnet steps, name the host SDK requirement, and give
CODESTYLE.md's .NET summary the global.json rule its intentRef needs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Unset, a netstandard2.0 analyzer or source-generator project compiles
at C# 7.3, which Nullable enable refuses (CS8630). Let it set the
TFM's fixed C# version, and keep latest, latestMajor, and preview
banned everywhere, in the skill and the audit check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings November 12, 2026 18:34
@coderabbitai

coderabbitai Bot commented Nov 12, 2026 •

Copy link
Copy Markdown

Explain Change →

Caution

Review failed

The pull request is closed.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

The netstandard exception had landed between "Those float with the
installed SDK's compiler." and the IDE0028/CS8652 sentence explaining
it, so that sentence read as a result of the fixed number.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Approval is blocked by two active documentation and audit-coverage issues: the SDK-dependent analyzer example is self-contradictory, and the audit assertion does not cover all imported props and targets files.

2 open issues
What changed in this PR

This pull request standardizes .NET SDK selection and C# language-version behavior across fleet repositories by requiring explicit SDK configuration and aligning language versions with target frameworks.

Changes:

  • Adds the csharp.sdk.globaljson project-type audit requirement.
  • Documents the required global.json, LangVersion, and TFM alignment rules.
  • Updates the .NET style summary and regenerates the distributed Copilot and Claude skill files.
File Description
spec/​project-types.json Adds the machine-readable C# SDK and language-version conformance check.
CODESTYLE.md Summarizes the new .NET SDK selection and C# language-version rules.
.github/​skills/​dotnet-codestyle/​SKILL.md Provides the generated GitHub Copilot skill guidance for SDK selection and C# versioning.
.github/​skills/​dotnet-codestyle/​references/​testing.md Provides the generated Copilot testing reference for shared SDK and test-runner configuration.
.github/​skills/​dotnet-codestyle/​references/​project-config.md Provides the generated Copilot project-configuration reference for TFM and SDK alignment.
.claude-plugin/​fleet-skills/​skills/​dotnet-codestyle/​SKILL.md Provides the generated Claude skill guidance for SDK selection and C# versioning.
.claude-plugin/​fleet-skills/​skills/​dotnet-codestyle/​references/​testing.md Provides the generated Claude testing reference for shared SDK and test-runner configuration.
.claude-plugin/​fleet-skills/​skills/​dotnet-codestyle/​references/​project-config.md Provides the generated Claude project-configuration reference for TFM and SDK alignment.
.claude-plugin/​fleet-skills/​.source-digests/​dotnet-codestyle Records the updated source digest for the distributed dotnet-codestyle skill.
.agents/​skills/​dotnet-codestyle/​SKILL.md Defines the canonical SDK selection and C# language-version guidance.
.agents/​skills/​dotnet-codestyle/​references/​testing.md Documents the canonical testing configuration tied to the shared SDK file.
.agents/​skills/​dotnet-codestyle/​references/​project-config.md Documents the canonical relationship between target frameworks and SDK lines.

Review effort: Lite

Comment thread spec/project-types.json Resolved
@ptr727

ptr727 commented Nov 12, 2026

Copy link
Copy Markdown
Owner Author

A recorded local strict-review pass covers head 9fd565ec0648de781b8e0bca4bffc860dd1fec43, the content this pull request carries at that commit against develop, and it recorded 0 findings.

ptr727 and others added 2 commits November 12, 2026 10:39
The audit check named only Directory.Build.props and .targets, so a
LangVersion set in an imported file such as build/Compiler.props
passed it while breaking the rule.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Answer the local pass on the Copilot fix: the check's LangVersion
scope reaches any props or targets file wherever it is imported, the
version must be the 100 band rather than any band on the major, a
global.json carrying only the test runner key is drift, and the
check's sentences are split to the prose length.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@codecov

codecov Bot commented Nov 12, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 76.58%. Comparing base (d0cbd27) to head (da157c0).

Additional details and impacted files
@@           Coverage Diff            @@
##           develop    #4109   +/-   ##
========================================
  Coverage    76.58%   76.58%           
========================================
  Files           40       40           
  Lines        14136    14136           
========================================
  Hits         10826    10826           
  Misses        3310     3310           
Flag Coverage Δ
python-3.13 76.58% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

A hub that switched setup-dotnet to the new line alone would leave
every repo still on the old global.json floor with no compatible SDK.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ptr727 and others added 3 commits November 12, 2026 10:51
The new csharp.sdk.globaljson check makes a root global.json required
for every C# repo, so the type's requiredFiles names it too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…vcontainer

Any later 1xx version is a higher floor that refuses a lagging distro
SDK, so the version must be exactly <major>.0.100. The LangVersion
rule covers only files the repo holds, since the SDK's own targets set
it, and bans EnablePreviewFeatures. The devcontainer image is a second
hub site that must provide both lines through a major move.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add catalog/snippets/configs/global.json and its spec/files.json
entry, so standup and the presence audit carry the file the new check
requires. Name LangVersion in the check's banned-value sentence, and
move a netstandard project's fixed LangVersion with the TFM.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ptr727

ptr727 commented Nov 12, 2026

Copy link
Copy Markdown
Owner Author

A recorded local strict-review pass covers head da157c00174a0d3920949716584aab0b7b419700, the content this pull request carries at that commit against develop, and it recorded 0 findings.

@ptr727

ptr727 commented Nov 12, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@ptr727

ptr727 commented Nov 12, 2026

Copy link
Copy Markdown
Owner Author

/review

@coderabbitai

coderabbitai Bot commented Nov 12, 2026 •

Copy link
Copy Markdown
Action not completed

Pull request is closed.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@ptr727
ptr727 merged commit 2362716 into develop Nov 12, 2026
13 checks passed
@ptr727
ptr727 deleted the feature/dotnet-sdk-line-global-json branch November 12, 2026 19:28
ptr727 added a commit that referenced this pull request Nov 12, 2026
… Upgrades (#4096)

## Summary

Promotes the agent-setup follow-ups and their review fixes, plus one
change from another hub session, from `develop` to `main`. Both follow a
native Windows 11 test of the one-step agent setup released as 2.0.1414.

- #4094:
- The Claude safety kit puts `"$defaults"` first in each `autoMode` list
that exists (`environment`, `allow`, `soft_deny`, `hard_deny`). Claude
Code's "learn rules" offer had written a list without it, which silently
replaced Claude Code's built-in rules. `--report` flags such a list as
not current.
  - The kit report's archive note names the commit.
- The Codex and opencode rules lines say when only an agent's config
directory makes it count as installed.
- `merge-and-release` step 7 also refreshes the Codex and opencode
rules, only where the kit reads current.
- #4095: an agent tool installed through npm, bun, scoop, Homebrew or
mise is upgraded through that manager, one package only. The manager is
asked whether it owns the tool, with every link resolved, before any
path shape is read, and the recorded package must own the file. A Node
runtime is never upgraded on an agent's behalf. Nothing elevates: choco,
a global scoop app, an unwritable npm prefix and Nix are reported with
their command. winget and apt stay with `upgrade-host`.

- #4102: answers this promotion's Copilot review. On Linux, npm is asked
before a `.bun` path, as on Windows, and a Nix agent under
`/nix/store/.../node_modules` is read as Nix before the generic npm
shape.

- #4105: answers this promotion's second Copilot round. On Windows,
`Test-ProtectedPath` and `Hide-Home` match only at a path component, so
`C:\Program FilesPortable` is no longer read as protected and a sibling
profile is no longer shortened. The pure path-helper tests now also run
on the native Windows CI runner.

- #4111: answers CodeRabbit's review of this promotion. bun's
`BUN_INSTALL` and `BUN_INSTALL_GLOBAL_DIR` are honored, including bun's
copied Windows shim. A mise shim is followed through `mise which`, and
mise's own listing is asked before any path shape. One herdr post step
runs after every successful upgrade. Scoop's configured roots are read
from its `config.json`.

- #4112: answers this promotion's attested local review. herdr's report
notes now match its post step for a manager-owned herdr.
`install-tools.ps1`'s `Hide-Home` gets #4105's component boundary. One
`Test-PathUnder` helper replaces seven hand-written containment checks.
A dead depth bound is removed.

- #4109, from another hub session: `dotnet-codestyle` now requires a
`global.json` pinning SDK `10.0.100` with `latestFeature` and
`allowPrerelease: false`. It leaves `LangVersion` unset (netstandard
generator projects excepted) and forbids `EnablePreviewFeatures`. The
audit gains the `csharp.sdk.globaljson` check, with a
`catalog/snippets/configs/global.json` snippet and its `spec/files.json`
C# baseline entry. `CODESTYLE.md`'s .NET summary line is updated.
Follow-ups #4106 and #4107 are filed and not in this promotion.

## Pre-existing Findings, Filed

- `host-setup/windows/install-tools.ps1:616` (`pre-existing`,
correctness): `Write-InstallFailure`'s profile replacement in log lines
does not stop at a path component. Filed as #4113.

## Not Verified

- Real package managers. #4095's tests use stub managers on PATH. The
Windows npm, scoop and bun layouts are modeled from their documented
formats and have not been run against real installs. The maintainer's
Windows 11 retest after this release covers the npm-installed opencode
case.

Closes #4103

🤖 Generated with [Claude Code](https://claude.com/claude-code)
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