--- key: ci.format-gate-folder-mode title: 2026-07-19 — The `format` gate runs `dotnet format whitespace . --folder`, not the full solution format (#469) status: active since: '2026-07-19' supersedes: none superseded-by: none rule: The blocking `format` CI job (and matching pre-commit hook) runs `dotnet format whitespace . --folder --include ` instead of loading the full MSBuild/Roslyn solution, cutting the gate from ~480s to ~0.5s with unchanged whitespace/charset coverage. signals: 'dotnet format, folder mode, CI format gate · paths: `.gitea/workflows` format job, `.editorconfig` · issues: #469, #406, #311' mechanics: '`dotnet format whitespace . --folder --verify-no-changes --include `' --- The blocking `format` CI job (and the matching Husky pre-commit hook) verify changed `.cs` files with `dotnet format whitespace . --folder --verify-no-changes --include ` instead of the previous `dotnet format ErsatzTV.sln --no-restore --verify-no-changes --include `. - **Why.** `--include` narrows *which* files are checked, never what gets loaded. The full recipe loaded the whole ~10-project MSBuild workspace and built a Roslyn compilation per project before checking a single line — a fixed cost independent of how few files changed. Measured **~480s** for a whole-solution `dotnet format` locally (matching the issue's "7+ min"). `--folder` treats the tree as a plain folder of files and skips MSBuild/Roslyn entirely: **~0.5s**, and it needs no `dotnet restore`, so the job's NuGet-cache + Restore steps were deleted. It also drops the job's ~3.95 GiB Roslyn heap (the #406 memory note about `format` not shrinking is now moot). - **Coverage is unchanged, not merely "good enough".** Folder mode reads `.editorconfig` and enforces exactly the two things this gate exists for — **whitespace** (indent/EOL/trailing/final-newline) and **charset** (no UTF-8 BOM). Proven non-vacuous: exits non-zero with `error WHITESPACE` on an injected trailing-whitespace line and `error CHARSET` on a prepended BOM; exits 0 on a clean file. What it drops is the style/analyzer pass — but the *full* gate never enforced that either: a probe injecting a `warning`-severity naming violation (`local_constants` not `ALL_UPPER`) **passed** the full solution format (exit 0): the only `.editorconfig` rule above `:suggestion`/`:none` severity is that one naming rule, and naming violations have no `dotnet format` batch code-fixer, so `--verify-no-changes` reports no change regardless of severity. The analyzers that must block (`NU1904`, `S3981`) are enforced at compile time via `WarningsAsErrors` in `Directory.Build.props`, never by this job. - **Fix command for a violation:** `dotnet format whitespace . --folder --include `. The full `dotnet format ErsatzTV.sln --include ` is a superset (also applies style) and still works, so existing muscle memory and the #311 lore's `dotnet format --include` guidance are not broken. - **Lane left on `ubuntu-latest`.** The job is now seconds-long and low-memory, so it could move to a lighter lane, but that re-touches the per-lane memory-cap accounting (#406/#604) and is a server-management capacity call — deliberately out of scope here.