From 1968f5c4e6355261669becb9bc83f5357bc68f02 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 31 Oct 2026 09:17:40 +0000 Subject: [PATCH 1/2] build: move the test suites to xunit.v3 4 and the Testing Platform xunit.v3 4 runs on Microsoft.Testing.Platform v2, which the .NET 10 SDK no longer drives through the VSTest mode of `dotnet test`. global.json opts `dotnet test` into the Testing Platform mode, so every command now names its target with --solution or --project and logs with --output. coverlet.collector is a VSTest data collector and stops working there. Every test project now references coverlet.MTP, and coverage.rsp replaces coverage.runsettings as the shared ci/sonar options: same OpenCover format, same measured modules, one report per test project named coverage.opencover..xml. Verify.XunitV3 stays on 32.0.1, which runs on xunit.v3 4: every 33.x release fails the build with SponsorCheck SC021 until a sponsorship or exemption is declared, a licensing decision left to the maintainer. Dependabot ignores 33 and later until then. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_019k6GsSYBeJ4fUz7QbEueQW --- .github/dependabot.yml | 6 +++++ .github/pull_request_template.md | 2 +- .github/workflows/canary.yml | 2 +- .github/workflows/ci.yml | 19 +++++++-------- .github/workflows/release.yml | 2 +- .github/workflows/sonar.yml | 11 ++++----- .gitignore | 2 ++ AGENTS.md | 2 +- CLAUDE.md | 4 ++-- CONTRIBUTING.md | 4 ++-- Directory.Packages.props | 10 ++++---- ...irstClassErrors.Analyzers.UnitTests.csproj | 3 +-- .../FirstClassErrors.Cli.UnitTests.csproj | 3 +-- .../FirstClassErrors.GenDoc.UnitTests.csproj | 3 +-- .../FirstClassErrors.PropertyTests.csproj | 3 +-- ...sErrors.RequestBinder.PropertyTests.csproj | 3 +-- ...ClassErrors.RequestBinder.UnitTests.csproj | 3 +-- ...rrors.RequestBinder.Usage.UnitTests.csproj | 3 +-- .../FirstClassErrors.Testing.UnitTests.csproj | 3 +-- .../FirstClassErrors.UnitTests.csproj | 3 +-- coverage.rsp | 16 +++++++++++++ coverage.runsettings | 23 ------------------- .../for-maintainers/workflows/ci.en.md | 8 +++---- .../for-maintainers/workflows/ci.fr.md | 8 +++---- .../for-maintainers/workflows/sonar.en.md | 2 +- .../for-maintainers/workflows/sonar.fr.md | 2 +- doc/handwritten/for-users/CONTRIBUTING.fr.md | 4 ++-- global.json | 3 +++ 28 files changed, 76 insertions(+), 81 deletions(-) create mode 100644 coverage.rsp delete mode 100644 coverage.runsettings diff --git a/.github/dependabot.yml b/.github/dependabot.yml index a337181f..4f3f3b0b 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -17,6 +17,12 @@ updates: # nuget config cannot scope the rule to one project, so these also freeze in the analyzer test project. - dependency-name: "Microsoft.CodeAnalysis.CSharp" - dependency-name: "Microsoft.CodeAnalysis.Common" + # Verify 33 added a build-time SponsorCheck (error SC021) that fails GenDoc.UnitTests unless the build + # declares a sponsorship, a licence or a time-bounded exemption — a licensing decision, not routine + # maintenance. Verify.XunitV3 32.x runs on xunit.v3 4 (its dependency is a 3.2.2 minimum), so it stays + # there until the maintainer settles that question. + - dependency-name: "Verify.XunitV3" + versions: [">= 33.0.0"] - package-ecosystem: "github-actions" directory: "/" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index a032169b..70386af2 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -38,7 +38,7 @@ * [ ] `dotnet build FirstClassErrors.sln` -* [ ] `dotnet test FirstClassErrors.sln` +* [ ] `dotnet test --solution FirstClassErrors.sln` * [ ] Analyzer tests pass (`FirstClassErrors.Analyzers.UnitTests`) ## Documentation diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml index 5c57c65f..0167b493 100644 --- a/.github/workflows/canary.yml +++ b/.github/workflows/canary.yml @@ -156,6 +156,6 @@ jobs: # the preview major. The env is scoped inline to the test call so it never touches build/evaluation. dotnet build "$proj/$proj.csproj" -c Release DOTNET_ROLL_FORWARD=LatestMajor DOTNET_ROLL_FORWARD_TO_PRERELEASE=1 \ - dotnet test "$proj/$proj.csproj" -c Release --no-build --logger "console;verbosity=normal" + dotnet test --project "$proj/$proj.csproj" -c Release --no-build --output Detailed echo "::endgroup::" done diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4e5af4e7..1f73722b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -53,21 +53,22 @@ jobs: run: dotnet build FirstClassErrors.sln -c Release --no-restore - name: Test - # Collect OpenCover coverage via coverlet.collector (configured in coverage.runsettings). - # Reports land under artifacts/coverage//coverage.opencover.xml, ready for a Sonar scan. + # Collect OpenCover coverage via coverlet.MTP (options in coverage.rsp). Reports land under + # artifacts/coverage/coverage.opencover..xml, one per test project, ready for a Sonar scan. + # '@coverage.rsp' is quoted: unquoted, PowerShell (the windows-latest default shell) parses it as its + # splatting operator and fails before dotnet runs. run: >- - dotnet test FirstClassErrors.sln -c Release --no-build - --collect:"XPlat Code Coverage" - --settings coverage.runsettings + dotnet test --solution FirstClassErrors.sln -c Release --no-build + '@coverage.rsp' --results-directory artifacts/coverage - --logger "console;verbosity=normal" + --output Detailed - name: Upload coverage report uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7 with: # Per-OS name so the two matrix legs do not clash when uploading. name: coverage-${{ matrix.os }} - path: artifacts/coverage/**/coverage.opencover.xml + path: artifacts/coverage/**/coverage.opencover.*.xml if-no-files-found: error # build-test above runs the suite on the LATEST .NET (10). This job proves the LIBRARY's OTHER supported @@ -110,8 +111,8 @@ jobs: FirstClassErrors.PropertyTests \ FirstClassErrors.RequestBinder.PropertyTests ; do echo "::group::$proj (net472)" - dotnet test "$proj/$proj.csproj" -c Release -f net472 -p:EnableNet472Floor=true \ - --logger "console;verbosity=normal" + dotnet test --project "$proj/$proj.csproj" -c Release -f net472 -p:EnableNet472Floor=true \ + --output Detailed echo "::endgroup::" done diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d88e5222..f8a44027 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -130,7 +130,7 @@ jobs: run: dotnet build FirstClassErrors.sln -c Release --no-restore -p:Version="$VERSION" - name: Test - run: dotnet test FirstClassErrors.sln -c Release --no-build --logger "console;verbosity=normal" + run: dotnet test --solution FirstClassErrors.sln -c Release --no-build --output Detailed # GenDoc ships bundled inside the fce tool (no package of its own -- see pack.sh), so a breaking # change to its own error catalog is a breaking change of the cli train. doc/generated/gendoc/ diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml index 085c4edc..d9298d1a 100644 --- a/.github/workflows/sonar.yml +++ b/.github/workflows/sonar.yml @@ -93,7 +93,7 @@ jobs: /o:"reefact" /d:sonar.token="$SONAR_TOKEN" /d:sonar.host.url="https://sonarcloud.io" - /d:sonar.cs.opencover.reportsPaths="artifacts/coverage/**/coverage.opencover.xml" + /d:sonar.cs.opencover.reportsPaths="artifacts/coverage/**/coverage.opencover.*.xml" /d:sonar.exclusions="**/*.verified.*" /d:sonar.coverage.exclusions="FirstClassErrors.RequestBinder.Benchmarks/**" /d:sonar.issue.ignore.multicriteria="s7682,s7679" @@ -112,13 +112,12 @@ jobs: run: dotnet build FirstClassErrors.sln -c Release -p:TreatWarningsAsErrors=false -p:MSBuildTreatWarningsAsErrors=false - name: Test with coverage - # Reuse coverage.runsettings so the OpenCover report matches the one the ci workflow produces. + # Reuse coverage.rsp so the OpenCover report matches the one the ci workflow produces. run: >- - dotnet test FirstClassErrors.sln -c Release --no-build - --collect:"XPlat Code Coverage" - --settings coverage.runsettings + dotnet test --solution FirstClassErrors.sln -c Release --no-build + '@coverage.rsp' --results-directory artifacts/coverage - --logger "console;verbosity=normal" + --output Detailed - name: End analysis env: diff --git a/.gitignore b/.gitignore index 5305c092..2b6f9099 100644 --- a/.gitignore +++ b/.gitignore @@ -61,6 +61,8 @@ artifacts/ *.pgc *.pgd *.rsp +# ...except the shared coverage options of `dotnet test` (ci and sonar workflows). +!/coverage.rsp *.sbr *.tlb *.tli diff --git a/AGENTS.md b/AGENTS.md index 97cf433a..7e4955fe 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -7,7 +7,7 @@ Two roles are covered: **writing code** and **reviewing pull requests**. - .NET Standard 2.0 library. Errors are first-class, documented, diagnosable concepts. - Build: `dotnet build FirstClassErrors.sln` -- Test: `dotnet test FirstClassErrors.sln` (analyzer tests: `dotnet test FirstClassErrors.Analyzers.UnitTests`). +- Test: `dotnet test --solution FirstClassErrors.sln` (analyzer tests: `dotnet test --project FirstClassErrors.Analyzers.UnitTests`). - Repository language is **English** (code, comments, commits, PRs, issues, and review comments). French lives only in `doc/handwritten/for-users/README.fr.md` and must stay in sync with the English README. diff --git a/CLAUDE.md b/CLAUDE.md index 51951c64..29ba70f2 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -19,9 +19,9 @@ errors should stay structured, documented, and close to the code. * Target framework: **.NET Standard 2.0**. * Build: `dotnet build FirstClassErrors.sln` -* Test: `dotnet test FirstClassErrors.sln` +* Test: `dotnet test --solution FirstClassErrors.sln` * Run the analyzer tests when touching analyzers: - `dotnet test FirstClassErrors.Analyzers.UnitTests` + `dotnet test --project FirstClassErrors.Analyzers.UnitTests` * Mutation testing measures every pull request on the files it changed, for every project whose code ships or runs (decisions: ADR-0043, and ADR-0046 which made the per-PR check **advisory** — it diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a15057b7..310415ce 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,8 +11,8 @@ library produces. This guide defines how commits are written here. * Target framework: **.NET Standard 2.0**. * Build: `dotnet build FirstClassErrors.sln` -* Test: `dotnet test FirstClassErrors.sln` -* Analyzer tests, when touching analyzers: `dotnet test FirstClassErrors.Analyzers.UnitTests` +* Test: `dotnet test --solution FirstClassErrors.sln` +* Analyzer tests, when touching analyzers: `dotnet test --project FirstClassErrors.Analyzers.UnitTests` See [`CLAUDE.md`](CLAUDE.md) for the project layout and the broader change guidelines. diff --git a/Directory.Packages.props b/Directory.Packages.props index 0510274d..468ba302 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -26,7 +26,7 @@ - + @@ -41,10 +41,10 @@ - - - - + + + + diff --git a/FirstClassErrors.Analyzers.UnitTests/FirstClassErrors.Analyzers.UnitTests.csproj b/FirstClassErrors.Analyzers.UnitTests/FirstClassErrors.Analyzers.UnitTests.csproj index d6f58260..9eaf3583 100644 --- a/FirstClassErrors.Analyzers.UnitTests/FirstClassErrors.Analyzers.UnitTests.csproj +++ b/FirstClassErrors.Analyzers.UnitTests/FirstClassErrors.Analyzers.UnitTests.csproj @@ -8,9 +8,8 @@ - + all - runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/FirstClassErrors.Cli.UnitTests/FirstClassErrors.Cli.UnitTests.csproj b/FirstClassErrors.Cli.UnitTests/FirstClassErrors.Cli.UnitTests.csproj index 3307e501..142638a8 100644 --- a/FirstClassErrors.Cli.UnitTests/FirstClassErrors.Cli.UnitTests.csproj +++ b/FirstClassErrors.Cli.UnitTests/FirstClassErrors.Cli.UnitTests.csproj @@ -8,9 +8,8 @@ - + all - runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/FirstClassErrors.GenDoc.UnitTests/FirstClassErrors.GenDoc.UnitTests.csproj b/FirstClassErrors.GenDoc.UnitTests/FirstClassErrors.GenDoc.UnitTests.csproj index 96d82e43..2469f76e 100644 --- a/FirstClassErrors.GenDoc.UnitTests/FirstClassErrors.GenDoc.UnitTests.csproj +++ b/FirstClassErrors.GenDoc.UnitTests/FirstClassErrors.GenDoc.UnitTests.csproj @@ -9,9 +9,8 @@ - + all - runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/FirstClassErrors.PropertyTests/FirstClassErrors.PropertyTests.csproj b/FirstClassErrors.PropertyTests/FirstClassErrors.PropertyTests.csproj index ce92872f..ebc1e0bf 100644 --- a/FirstClassErrors.PropertyTests/FirstClassErrors.PropertyTests.csproj +++ b/FirstClassErrors.PropertyTests/FirstClassErrors.PropertyTests.csproj @@ -11,9 +11,8 @@ - + all - runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/FirstClassErrors.RequestBinder.PropertyTests/FirstClassErrors.RequestBinder.PropertyTests.csproj b/FirstClassErrors.RequestBinder.PropertyTests/FirstClassErrors.RequestBinder.PropertyTests.csproj index d5d3914f..619fa800 100644 --- a/FirstClassErrors.RequestBinder.PropertyTests/FirstClassErrors.RequestBinder.PropertyTests.csproj +++ b/FirstClassErrors.RequestBinder.PropertyTests/FirstClassErrors.RequestBinder.PropertyTests.csproj @@ -13,9 +13,8 @@ - + all - runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/FirstClassErrors.RequestBinder.UnitTests/FirstClassErrors.RequestBinder.UnitTests.csproj b/FirstClassErrors.RequestBinder.UnitTests/FirstClassErrors.RequestBinder.UnitTests.csproj index 1e29a580..624dd715 100644 --- a/FirstClassErrors.RequestBinder.UnitTests/FirstClassErrors.RequestBinder.UnitTests.csproj +++ b/FirstClassErrors.RequestBinder.UnitTests/FirstClassErrors.RequestBinder.UnitTests.csproj @@ -8,9 +8,8 @@ - + all - runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/FirstClassErrors.RequestBinder.Usage.UnitTests/FirstClassErrors.RequestBinder.Usage.UnitTests.csproj b/FirstClassErrors.RequestBinder.Usage.UnitTests/FirstClassErrors.RequestBinder.Usage.UnitTests.csproj index c7daa200..68ab508d 100644 --- a/FirstClassErrors.RequestBinder.Usage.UnitTests/FirstClassErrors.RequestBinder.Usage.UnitTests.csproj +++ b/FirstClassErrors.RequestBinder.Usage.UnitTests/FirstClassErrors.RequestBinder.Usage.UnitTests.csproj @@ -8,9 +8,8 @@ - + all - runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/FirstClassErrors.Testing.UnitTests/FirstClassErrors.Testing.UnitTests.csproj b/FirstClassErrors.Testing.UnitTests/FirstClassErrors.Testing.UnitTests.csproj index bb10cede..2ba81743 100644 --- a/FirstClassErrors.Testing.UnitTests/FirstClassErrors.Testing.UnitTests.csproj +++ b/FirstClassErrors.Testing.UnitTests/FirstClassErrors.Testing.UnitTests.csproj @@ -8,9 +8,8 @@ - + all - runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/FirstClassErrors.UnitTests/FirstClassErrors.UnitTests.csproj b/FirstClassErrors.UnitTests/FirstClassErrors.UnitTests.csproj index 2b8b6632..12838a78 100644 --- a/FirstClassErrors.UnitTests/FirstClassErrors.UnitTests.csproj +++ b/FirstClassErrors.UnitTests/FirstClassErrors.UnitTests.csproj @@ -11,9 +11,8 @@ - + all - runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/coverage.rsp b/coverage.rsp new file mode 100644 index 00000000..f39813e7 --- /dev/null +++ b/coverage.rsp @@ -0,0 +1,16 @@ +# Coverage options for `dotnet test`, shared by the ci and sonar workflows: `dotnet test ... '@coverage.rsp'`. +# Keep the quotes: unquoted, PowerShell parses @coverage as its splatting operator. +# +# Drives the coverlet.MTP extension (referenced by every test project) to emit OpenCover XML. SonarQube / +# SonarCloud reads C# coverage from OpenCover via sonar.cs.opencover.reportsPaths; it does not consume +# coverlet's default Cobertura output. Keeping the options here rather than in each workflow means local runs +# and CI produce identical reports. +# +# Command-line options, not a testconfig.json: a coverlet configuration file is authoritative and switches +# off coverlet's default exclusions (generated and compiler-generated code, ExcludeFromCodeCoverage, the test +# assemblies themselves), which these options keep and only extend with Obsolete. +--coverlet +--coverlet-output-format +opencover +--coverlet-exclude-by-attribute +Obsolete diff --git a/coverage.runsettings b/coverage.runsettings deleted file mode 100644 index 6c694d61..00000000 --- a/coverage.runsettings +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - opencover - - Obsolete,GeneratedCodeAttribute,CompilerGeneratedAttribute - - - - - diff --git a/doc/handwritten/for-maintainers/workflows/ci.en.md b/doc/handwritten/for-maintainers/workflows/ci.en.md index ca3c7bf3..b1ec3994 100644 --- a/doc/handwritten/for-maintainers/workflows/ci.en.md +++ b/doc/handwritten/for-maintainers/workflows/ci.en.md @@ -39,9 +39,9 @@ On a `[ubuntu-latest, windows-latest]` matrix: 1. Checkout, then set up the .NET SDK. 2. `dotnet restore` → `dotnet build -c Release` → `dotnet test -c Release`. -3. Tests collect OpenCover coverage via `coverlet.collector`, configured by - [`coverage.runsettings`](../../../../coverage.runsettings), into - `artifacts/coverage//coverage.opencover.xml`. +3. Tests collect OpenCover coverage via `coverlet.MTP`, configured by + [`coverage.rsp`](../../../../coverage.rsp), into + `artifacts/coverage/coverage.opencover..xml` (one per test project). 4. The coverage report is uploaded as a per-OS artifact. ### `floor` — the tooling on its minimum runtime @@ -96,7 +96,7 @@ secrets and needs no write scope. ## Related -- [`sonar`](sonar.en.md) reuses the same `coverage.runsettings` so its coverage +- [`sonar`](sonar.en.md) reuses the same `coverage.rsp` so its coverage report matches this one. - [`analyzers`](analyzers.en.md) covers the analyzer dogfood that `ci` does not. - [`canary.yml`](../../../../.github/workflows/canary.yml) *(no reference page yet)* diff --git a/doc/handwritten/for-maintainers/workflows/ci.fr.md b/doc/handwritten/for-maintainers/workflows/ci.fr.md index c9fd1592..452ee804 100644 --- a/doc/handwritten/for-maintainers/workflows/ci.fr.md +++ b/doc/handwritten/for-maintainers/workflows/ci.fr.md @@ -41,9 +41,9 @@ Sur une matrice `[ubuntu-latest, windows-latest]` : 1. Checkout, puis installation du SDK .NET. 2. `dotnet restore` → `dotnet build -c Release` → `dotnet test -c Release`. -3. Les tests collectent la couverture OpenCover via `coverlet.collector`, - configuré par [`coverage.runsettings`](../../../../coverage.runsettings), dans - `artifacts/coverage//coverage.opencover.xml`. +3. Les tests collectent la couverture OpenCover via `coverlet.MTP`, + configuré par [`coverage.rsp`](../../../../coverage.rsp), dans + `artifacts/coverage/coverage.opencover..xml` (un par projet de test). 4. Le rapport de couverture est uploadé en artefact, un par OS. ### `floor` — l'outillage sur son runtime minimum @@ -100,7 +100,7 @@ stocke aucun secret et n'a besoin d'aucun périmètre en écriture. ## En rapport -- [`sonar`](sonar.fr.md) réutilise le même `coverage.runsettings` pour que son +- [`sonar`](sonar.fr.md) réutilise le même `coverage.rsp` pour que son rapport de couverture corresponde à celui-ci. - [`analyzers`](analyzers.fr.md) couvre le dogfood des analyzers que `ci` ne fait pas. diff --git a/doc/handwritten/for-maintainers/workflows/sonar.en.md b/doc/handwritten/for-maintainers/workflows/sonar.en.md index 99c26d3b..3d8c11e7 100644 --- a/doc/handwritten/for-maintainers/workflows/sonar.en.md +++ b/doc/handwritten/for-maintainers/workflows/sonar.en.md @@ -60,4 +60,4 @@ the **SonarQube Cloud GitHub App**, not by this workflow's token, so no ## Related - [`ci`](ci.en.md) — produces the same OpenCover coverage shape via the shared - `coverage.runsettings`, and is where the warning ratchet is actually enforced. + `coverage.rsp`, and is where the warning ratchet is actually enforced. diff --git a/doc/handwritten/for-maintainers/workflows/sonar.fr.md b/doc/handwritten/for-maintainers/workflows/sonar.fr.md index 8c59a95f..6d376360 100644 --- a/doc/handwritten/for-maintainers/workflows/sonar.fr.md +++ b/doc/handwritten/for-maintainers/workflows/sonar.fr.md @@ -63,5 +63,5 @@ s'authentifie avec le secret `SONAR_TOKEN`. ## En rapport - [`ci`](ci.fr.md) — produit la même forme de couverture OpenCover via le - `coverage.runsettings` partagé, et c'est là que le cliquet de warnings est + `coverage.rsp` partagé, et c'est là que le cliquet de warnings est réellement imposé. diff --git a/doc/handwritten/for-users/CONTRIBUTING.fr.md b/doc/handwritten/for-users/CONTRIBUTING.fr.md index 1116cd89..393d0752 100644 --- a/doc/handwritten/for-users/CONTRIBUTING.fr.md +++ b/doc/handwritten/for-users/CONTRIBUTING.fr.md @@ -12,8 +12,8 @@ commits sont écrits ici. * Framework cible : **.NET Standard 2.0**. * Compiler : `dotnet build FirstClassErrors.sln` -* Tester : `dotnet test FirstClassErrors.sln` -* Tests des analyzers, lorsque vous touchez aux analyzers : `dotnet test FirstClassErrors.Analyzers.UnitTests` +* Tester : `dotnet test --solution FirstClassErrors.sln` +* Tests des analyzers, lorsque vous touchez aux analyzers : `dotnet test --project FirstClassErrors.Analyzers.UnitTests` Voir [`CLAUDE.md`](../../../CLAUDE.md) pour l’organisation du projet et les lignes directrices plus larges concernant les changements. diff --git a/global.json b/global.json index d46d21e5..df32a2e3 100644 --- a/global.json +++ b/global.json @@ -3,5 +3,8 @@ "version": "10.0.100", "rollForward": "latestFeature", "allowPrerelease": false + }, + "test": { + "runner": "Microsoft.Testing.Platform" } } From 6d3fb048a92db7fcda8b4538cc5fc8b91e4707f2 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 31 Oct 2026 09:30:12 +0000 Subject: [PATCH 2/2] docs: answer review feedback with Conventional Comments reply labels Vendor the respond-to-review skill verbatim from Reefact/conventional-comments-toolkit (commit 996a6fd) under .claude/skills/, and point AGENTS.md and CLAUDE.md at it. Review replies now carry a reply label (done, ack, disagree, thanks, note, question) instead of the free-form "Resolved in ", agents never post decision or reviewed, and a blocking thread is left to its reviewer. The escalation routes to @reefact are unchanged. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_019k6GsSYBeJ4fUz7QbEueQW --- .claude/skills/respond-to-review/SKILL.md | 125 ++++++++++++++++++++++ AGENTS.md | 19 +++- CLAUDE.md | 11 +- 3 files changed, 148 insertions(+), 7 deletions(-) create mode 100644 .claude/skills/respond-to-review/SKILL.md diff --git a/.claude/skills/respond-to-review/SKILL.md b/.claude/skills/respond-to-review/SKILL.md new file mode 100644 index 00000000..bee5b62e --- /dev/null +++ b/.claude/skills/respond-to-review/SKILL.md @@ -0,0 +1,125 @@ +--- +name: respond-to-review +description: As the author of a GitHub pull request, answer its review findings and questions with Conventional Comments reply labels — `done`, `ack`, `disagree`, `thanks`, plus `note` and `question` — fix what needs fixing, and push. Use when a pull request you wrote receives review comments, or when asked to address a review. Never posts `reviewed` or `decision`, never approves, never merges. +--- + +# Respond to a review + +You are the author of the pull request: you wrote its code, and you are answering its review. +Every finding or question a reviewer raises gets an answer, in its own thread, and the answer +says what you did about it. A reviewer's `reviewed:` comment is not one of them: it closes their +review, raises no point and asks nothing, so it needs no reply. + +## 0. Language + +**Write every reply in the language the repository requires.** Look for it before posting: +`CLAUDE.md`, `AGENTS.md`, `CONTRIBUTING.md`, or any other contribution guide the repository keeps. +A rule there wins over everything else — including the language the reviewer wrote in, and the +language of this skill. Without such a rule, answer in the language of the comment you reply to. + +The same rule applies to everything else you write on the pull request: its title, its +description, and your commit messages, which a repository often constrains separately. + +Only the prose follows that language. Labels and identifiers (`done`, `disagree`, a function +name) are never translated. + +## 1. Conventional Comments + +Follow https://conventionalcomments.org/ and the extensions of the Conventional Comments Toolkit +(https://github.com/Reefact/conventional-comments-toolkit/blob/main/README.md). + +**Read the repository's configuration first**: `.conventional-comments.json` at the repository +root, if it exists. A reply label it disables does not exist for this repository: answer with +what it leaves enabled, or in plain text where replies need no label. + +**That file is not the whole configuration.** The labels in force come from three levels, merged +in this order: the toolkit's defaults, then the **organisation's configuration**, then the +repository's file, each overriding the previous one label by label; an **enterprise floor** can +then force some labels on. The organisation's configuration and the floor reach the extension +through the browser's enterprise policy, so you usually cannot see them. Therefore: + +- if the person you work for gives you the organisation's configuration, apply it before the + repository's file; +- otherwise, use only labels you can confirm: those the repository's file declares or enables, and + the toolkit's defaults it does not disable — never one the file disables. Do not guess an + organisation's custom labels; +- say in your report that the organisation's configuration was not visible to you, if it was not. + +Every reply starts with: + +`