centralize SDK analyzers at latest-All and enable threading analyzers for every centrally managed project
keep the complete .NET 10 SDK rule inventory visible at suggestion severity via a checked-in 281-rule globalconfig baseline
promote Sonar S3981 to a repo-wide CI blocker
fix the always-true worker-count predicate and add idle/active-worker regression tests
preserve the gitignored non-CPM MCP tool and copy the analyzer baseline into Docker restore/publish layers
update static-analysis and formatting documentation
Root cause
ReleaseMemoryHandler tested Workers.Count >= 0. A collection count cannot be negative, so every non-forced scheduled release was classified as busy and the intended aggressive idle-GC branch was unreachable.
The analyzer rollout also exposed an SDK precedence detail: latest-All injects exact per-ID severities, which outrank a bulk .editorconfig suggestion. The checked-in SDK baseline uses exact IDs at a higher global-config level, so All-only rules remain enabled and visible without turning the inherited backlog into hundreds of errors. Per-rule repository promotions still override it.
Verification
TZ=UTC dotnet restore ErsatzTV.sln -v minimal
TZ=UTC dotnet build ErsatzTV.sln --no-restore -v minimal (passes; 20 pre-existing compiler nullability warnings on a full rebuild)
## Summary
- centralize SDK analyzers at `latest-All` and enable threading analyzers for every centrally managed project
- keep the complete .NET 10 SDK rule inventory visible at suggestion severity via a checked-in 281-rule globalconfig baseline
- promote Sonar `S3981` to a repo-wide CI blocker
- fix the always-true worker-count predicate and add idle/active-worker regression tests
- preserve the gitignored non-CPM MCP tool and copy the analyzer baseline into Docker restore/publish layers
- update static-analysis and formatting documentation
## Root cause
`ReleaseMemoryHandler` tested `Workers.Count >= 0`. A collection count cannot be negative, so every non-forced scheduled release was classified as busy and the intended aggressive idle-GC branch was unreachable.
The analyzer rollout also exposed an SDK precedence detail: `latest-All` injects exact per-ID severities, which outrank a bulk `.editorconfig` suggestion. The checked-in SDK baseline uses exact IDs at a higher global-config level, so All-only rules remain enabled and visible without turning the inherited backlog into hundreds of errors. Per-rule repository promotions still override it.
## Verification
- `TZ=UTC dotnet restore ErsatzTV.sln -v minimal`
- `TZ=UTC dotnet build ErsatzTV.sln --no-restore -v minimal` (passes; 20 pre-existing compiler nullability warnings on a full rebuild)
- `TZ=UTC dotnet test ErsatzTV.sln --no-build -v quiet --logger "console;verbosity=quiet"` (3,688 passed, 1 skipped)
- changed-file `dotnet format --verify-no-changes`
- evaluated test-project properties: SDK analyzers enabled, `AnalysisLevel=latest-All`, threading analyzers enabled, checked-in globalconfig loaded
- negative control: temporarily restoring `Count >= 0` fails the build only on `S3981`
- gitignored non-CPM MCP restore: reproduced `NU1015` before the guard and passes after it
- pre-push API generation, lint, typecheck, and production web build
## Deferred / limitations
- full-tree formatting normalization remains a separate decision; format-as-you-touch stays enforced
- a coverage floor remains deferred until CI summaries establish a stable baseline
- the SDK globalconfig must be deliberately regenerated and reviewed on a future .NET SDK major upgrade
- active-process and forced-override memory-handler branches were unchanged and remain outside this focused regression test
- Docker is unavailable on the development workstation; the Dockerfile now copies the exact missing build input, but no local image build is claimed
Fixes #15
Reviewer response for blocked verdict on d3008b4c:
Docker globalconfig input — fixed in 2b8b16a5: the build stage now copies eng/analyzers/sdk-all-suggestion.globalconfig before restore/publish, matching the unconditional path in Directory.Build.props.
Non-CPM .mcp restore — fixed: the threading analyzer PackageReference now shares the ManagePackageVersionsCentrally=true guard used by the curated packs. The exact local MCP restore changed from NU1015 failure to exit 0; docs now state the centrally managed-project boundary.
Decision-matrix coverage — deferred as non-blocking: this regression changes only the empty-vs-nonempty worker-count decision and covers both sides. Active FFmpeg-process and forced-override behavior were not changed; expanding those branches can be a separate focused test increment.
Post-fix verification: full restore/build pass, 3,644 tests pass (1 intentional skip), MCP restore passes, pre-push API/lint/typecheck/web build passes. Docker is unavailable on this workstation, so no local image build is claimed; the Dockerfile now supplies the exact previously missing build input.
Requesting a fresh adversarial review of current head 2b8b16a5.
Reviewer response for blocked verdict on `d3008b4c`:
- **Docker globalconfig input — fixed** in `2b8b16a5`: the build stage now copies `eng/analyzers/sdk-all-suggestion.globalconfig` before restore/publish, matching the unconditional path in `Directory.Build.props`.
- **Non-CPM .mcp restore — fixed**: the threading analyzer PackageReference now shares the `ManagePackageVersionsCentrally=true` guard used by the curated packs. The exact local MCP restore changed from `NU1015` failure to exit 0; docs now state the centrally managed-project boundary.
- **Decision-matrix coverage — deferred as non-blocking**: this regression changes only the empty-vs-nonempty worker-count decision and covers both sides. Active FFmpeg-process and forced-override behavior were not changed; expanding those branches can be a separate focused test increment.
Post-fix verification: full restore/build pass, 3,644 tests pass (1 intentional skip), MCP restore passes, pre-push API/lint/typecheck/web build passes. Docker is unavailable on this workstation, so no local image build is claimed; the Dockerfile now supplies the exact previously missing build input.
Requesting a fresh adversarial review of current head `2b8b16a5`.
Fresh adversarial re-review completed against the current head.
- The CPM guard preserves analyzer packages for centrally managed projects while excluding the non-CPM `.mcp` tool.
- The generated analyzer globalconfig is copied before Docker restore/publish and is not excluded by `.dockerignore`.
- The SDK analyzer snapshot still exactly matches .NET SDK 10.0.301, including `CA1516 = none`.
- The remaining active-process/forced-override test gap is low-severity, non-blocking coverage debt; those branches were unchanged.
CI remains a separate merge gate.
Review-verdict: MERGEABLE @ 2b8b16a5884441988aafe3aa0624c8a2fbe9d21f
Fresh adversarial re-review completed after the required rebase onto `main` (`dd273fbb`).
- The rebased base-to-head patch is byte-for-byte identical to the previously reviewed patch.
- The CPM guard still excludes the non-CPM `.mcp` tool while loading analyzers for centrally managed projects.
- Docker still copies the generated analyzer globalconfig before restore/publish, and `.dockerignore` permits it.
- Evaluated properties remain `latest-All` with SDK and threading analyzers enabled.
- The 281-rule baseline still exactly matches .NET SDK 10.0.301, including `CA1516 = none`.
- The active-process/forced-override test gap remains low-severity, non-blocking coverage debt.
CI remains a separate merge gate.
Review-verdict: MERGEABLE @ 4ddc22937563e320cc767db9b8a9a7f81c168b96
Final adversarial re-review completed after rebasing onto merged PR #374.
- The analyzer feature patch is byte-for-byte identical to the previously reviewed patch.
- PR #374 changed no analyzer/MSBuild/Docker configuration and introduced no `S3981` conflict or threading suppression.
- Current evaluation still loads all analyzer packages for CPM projects and excludes the non-CPM `.mcp` project.
- Docker/globalconfig and SDK-inventory checks remain valid.
- The post-rebase full build and 3,688-pass test run confirm the newly merged IPTV code compiles cleanly under the promoted analyzer posture.
CI remains a separate merge gate.
Review-verdict: MERGEABLE @ 10ae885b4750495458a921958273af8746e5f265
timothy
merged commit dbd4bb43f7 into main2026-07-16 22:19:07 +02:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
latest-Alland enable threading analyzers for every centrally managed projectS3981to a repo-wide CI blockerRoot cause
ReleaseMemoryHandlertestedWorkers.Count >= 0. A collection count cannot be negative, so every non-forced scheduled release was classified as busy and the intended aggressive idle-GC branch was unreachable.The analyzer rollout also exposed an SDK precedence detail:
latest-Allinjects exact per-ID severities, which outrank a bulk.editorconfigsuggestion. The checked-in SDK baseline uses exact IDs at a higher global-config level, so All-only rules remain enabled and visible without turning the inherited backlog into hundreds of errors. Per-rule repository promotions still override it.Verification
TZ=UTC dotnet restore ErsatzTV.sln -v minimalTZ=UTC dotnet build ErsatzTV.sln --no-restore -v minimal(passes; 20 pre-existing compiler nullability warnings on a full rebuild)TZ=UTC dotnet test ErsatzTV.sln --no-build -v quiet --logger "console;verbosity=quiet"(3,688 passed, 1 skipped)dotnet format --verify-no-changesAnalysisLevel=latest-All, threading analyzers enabled, checked-in globalconfig loadedCount >= 0fails the build only onS3981NU1015before the guard and passes after itDeferred / limitations
Fixes #15
Reviewer response for blocked verdict on
d3008b4c:2b8b16a5: the build stage now copieseng/analyzers/sdk-all-suggestion.globalconfigbefore restore/publish, matching the unconditional path inDirectory.Build.props.ManagePackageVersionsCentrally=trueguard used by the curated packs. The exact local MCP restore changed fromNU1015failure to exit 0; docs now state the centrally managed-project boundary.Post-fix verification: full restore/build pass, 3,644 tests pass (1 intentional skip), MCP restore passes, pre-push API/lint/typecheck/web build passes. Docker is unavailable on this workstation, so no local image build is claimed; the Dockerfile now supplies the exact previously missing build input.
Requesting a fresh adversarial review of current head
2b8b16a5.Fresh adversarial re-review completed against the current head.
.mcptool..dockerignore.CA1516 = none.CI remains a separate merge gate.
Review-verdict: MERGEABLE @ 2b8b16a5884441988aafe3aa0624c8a2fbe9d21f
2b8b16a588to4ddc229375Fresh adversarial re-review completed after the required rebase onto
main(dd273fbb)..mcptool while loading analyzers for centrally managed projects..dockerignorepermits it.latest-Allwith SDK and threading analyzers enabled.CA1516 = none.CI remains a separate merge gate.
Review-verdict: MERGEABLE @ 4ddc22937563e320cc767db9b8a9a7f81c168b96
4ddc229375to10ae885b47Final adversarial re-review completed after rebasing onto merged PR #374.
S3981conflict or threading suppression..mcpproject.CI remains a separate merge gate.
Review-verdict: MERGEABLE @
10ae885b47