v0.15.2
[0.15.2] - 2026-08-01
Seven defects found after 0.15.0 shipped — six by the review, one by CI on macOS.
0.15.1 is 0.15.0. A
v0.15.1tag was created on the 0.15.0 commit by mistake and the release
pipeline published it before it could be stopped; deleting a pushed tag was not authorised. The
package is byte-identical to 0.15.0 and contains none of the fixes below. Use 0.15.2.
Fixed
-
WorkspaceNotLoadedon the first tool call after start. The 0.15.0 fix for the cold-start
handshake (I28) started the stdio transport before callingPreload, which is what assigns the
readytask every tool awaits. That opened a window where a request arriving immediately found an
empty registry and was answeredERROR WorkspaceNotLoadedinstead of waiting. Reproduced by CI on
macOS (ReadOnlyServerE2ETests.ReadTools_StillWork), which is the runner fast enough to hit it.
Preloadis assigned on the startup path again; the heavy work stays off it via theTask.Run
introduced in 0.15.0, so the handshake is still not blocked by MSBuild registration or the first load. -
PathBoundary.SameFileno longer callsFile.ResolveLinkTargeton every comparison. Because||
short-circuits the other way, the symlink clause added in 0.15.0 ran a filesystem syscall on both
operands for every pair that did not match — the common case in every scan over documents. Measured
at ~108 µs per non-matching call, ~270× slower than 0.14.0 (8 ms → 2 164 ms over 20 000
comparisons), onDocumentLookup,CodeFixService(per diagnostic × per file × up to 25 passes) and
RazorContext. Worse, it did not do what it was added for: a symlinked worktree is a directory
link, soFile.ResolveLinkTargeton the solution file returnsnull. Link resolution now lives in
WorkspaceRegistryidentity only, resolves the parent directory withDirectory.ResolveLinkTarget,
and runs once perload_workspacerather than once per comparison. -
A
.razoredit invalidates the generated-symbol cache again. 0.15.0 replaced
RazorIndex.InvalidatewithSync.Noticedand deleted the method — which wasRazorGeneratedMap.Forget's
only caller. Since that map self-invalidates only on a count change, editing a component's content
leftrazor_usages,razor_codebehindandrename_symbolresolving members from the pre-edit
compilation, taggedEXACT, for the life of the process.Noticednow forgets the map on a Razor bump. -
project_*,package_*andsolution_*no longer force a solution reload for adryRun. The
0.15.0 write-guard notified on anyIsOk, and adryRunreturnsIsOk;ChangeKind.Project
unconditionally requests a rebuild, so previewing a diff cost a full MSBuild reload on the next call. -
solution_add_projectandsolution_remove_projectnotify the solution file they actually wrote,
not the.csprojargument — which forproject_createmay not even exist yet. -
cleanup ids=is case-insensitive again. The 0.15.0 analyzer filter compared ids ordinally while
the result filter usedOrdinalIgnoreCase, socleanup fix=all ids=ca1822selected no analyzer,
produced no diagnostics and reported a clean pass having fixed nothing — a silent wrong answer. -
The XAML
Mentionspre-filter and the binding finder share one predicate. The filter only looked
at values starting with{whileXamlBindingServicematches a binding anywhere in the value, so
Text=" {Binding Amount}"could makerename_symbolskip the file and report success. -
GeneratedCode.InOutputDirectorytests the final path segment again, matching pre-0.15.0 behaviour for
a path that ends inobjorbin.
Full Changelog: v0.15.1...v0.15.2