build(hygiene): ship symbols, gate warnings, align casing (#121) - #143
Merged
Conversation
Four build-infrastructure gaps from the issue, plus the deployed paths that carried the same defect. Release shipped no symbols: DebugSymbols=False and DebugType=None meant every stack trace in the Serilog file landed without a file or line number. The log was never empty — exceptions are passed as objects and the template renders them, so type, message and the frame chain all arrived — but the ` in <file>:line <n>` suffix did not, and on a long trace through the sync executor knowing the method is not enough to know which branch threw. DebugType=portable now, and the installer picks the PDB up on its own because it copies the publish directory whole. Nothing enforced the zero-warning state, so it could rise silently. TreatWarningsAsErrors and EnforceCodeStyleInBuild are set centrally. NuGet audit codes NU1900-NU1904 are exempt: an advisory published against a transitive package, or an unreachable audit feed, would otherwise fail CI with no change in the repository. AnalysisLevel is deliberately absent for the same reason — global.json rolls forward across feature bands, so `latest` would move on its own. EnforceCodeStyleInBuild alone did not gate the .editorconfig naming rules. The dotnet_naming_rule severities drive the IDE; build enforcement reads dotnet_diagnostic.IDE1006.severity, which was unset. Adding that one line is what makes the gate bite, and it matters because CI runs no dotnet format step and the pre-commit hook is not versioned — a fresh clone has no style enforcement at all without it. InternalsVisibleTo was declared two ways, the SDK item in Core and a raw AssemblyAttribute in UI. One spelling now, matching Core. The assembly was named Semistep while the product and every namespace are SemiStep. The name is load-bearing in XAML: eleven avares:// URIs and one assembly= reference resolve against it, and the headless suite boots the real App, so a broken rename would have failed all 615 AvaloniaFact tests as a group. It did not. The deployed C:\DISTR\Config\ and C:\DISTR\Logs\ roots are recased to match, in StartupOptions and in the installer, which duplicate those literals by hand with nothing checking that they agree. The six [InstallDelete] entries clearing the legacy flat config layout are removed rather than recased. No machine carries that layout, so the cleanup has nothing left to do. Verified: clean Release build 0 warnings 0 errors, 1444 tests passed, publish emits SemiStep.pdb, ISCC compiles the installer with the new defines, and both gates were proven to bite by introducing a violation and watching the build fail. Closes #121 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
mrcsin
marked this pull request as ready for review
July 21, 2026 15:59
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #121.
Problem
Four build-infrastructure gaps, plus the deployed paths that carried the same defect.
DebugSymbols=FalseandDebugType=Nonemeant every stacktrace in the Serilog file landed without a file or line number. The log was never empty —
exceptions are passed as objects and the template renders them, so type, message and the
frame chain all arrived — but the
in <file>:line <n>suffix did not, and on a long tracethrough the sync executor knowing the method is not enough to know which branch threw.
InternalsVisibleTowas declared two ways — the SDK item in Core, a rawAssemblyAttributein UI.Semistepwhile the product and every namespace areSemiStep.The deployed
C:\DISTR\Config\andC:\DISTR\Logs\roots carried the same casing.What changed
DebugType=portablefor Release. The installer picks the PDB up on its own — it copies thepublish directory whole and excludes nothing.
TreatWarningsAsErrorsandEnforceCodeStyleInBuildset centrally. NuGet audit codesNU1900-NU1904are exempt: an advisory published against a transitive package, or anunreachable audit feed, would otherwise fail CI with no change in the repository.
AnalysisLevelis deliberately absent for the same reason —global.jsonrolls forwardacross feature bands, so
latestwould move on its own.dotnet_diagnostic.IDE1006.severity = warningin.editorconfig. This is what makes thestyle gate actually bite:
EnforceCodeStyleInBuildalone does not, because thedotnet_naming_ruleseverities drive the IDE rather than the build. It matters because CIruns no
dotnet formatstep and the pre-commit hook is not versioned, so a fresh clone hadno style enforcement at all.
InternalsVisibleTo, matching Core.AssemblyName→SemiStep, with the elevenavares://URIs and oneassembly=referencethat resolve against it, the installer's
AppExeName,.zed/debug.jsonand the localizationdoc. The deployed roots are recased in
StartupOptionsand in the installer.[InstallDelete]entries clearing the legacy flat config layout are removed ratherthan recased — no machine carries that layout, so the cleanup has nothing left to do.
.github/workflows/ci.ymlpathsgainsSemiStep.slnxand.editorconfig; both now definethe build and a change to either alone would not have triggered CI.
Docs/architecture/build-and-deployment.mdrecords the gate, the audit exemption, theIDE1006 finding, and the fact that
StartupOptions.csandInstaller/SemiStep.issduplicatethe deployed literals with nothing checking that they agree.
Verification
dotnet test SemiStep.slnx— 1444 passed, 0 faileddotnet publishemitsSemiStep.pdbalongsideSemiStep.exeISCC.execompiles the installer with the newSrcCfgDir/ConfigRoot/LogRootdefinesCS0219, a private field violating thenaming rule fails with
IDE1006Appand loadsavares://SemiStep/Styles/ColorPalette.axaml, so a broken rename would have failed all 615AvaloniaFacttests as a group. It did not.Note for reviewers
The
C:\DISTRrename is safe on an existing installation because NTFS is case-insensitive:Config\Semistep\andConfig\SemiStep\are the same directory, so an upgraded machine keepsreading its configuration and the installer overwrites in place. Nothing is stranded.
The deployed literals live in two places by hand —
StartupOptions.csandInstaller/SemiStep.iss— and nothing at build time checks that they agree. The only detectionis a manual install. That is documented rather than fixed here.