Repository navigation
Add analyzer banning non-deterministic calls in CRDT change types - #2815
hahn-kev-bot wants to merge 2 commits into
Conversation
Harmony replays every change on every client, so a Guid.NewGuid or DateTime.Now inside a change type's ApplyChange/NewEntity path (or a helper it calls) produces different state per client. The new rule flags a deny-list of well-known non-deterministic members anywhere in an IChange implementation except its instance constructors, which run once on the originating client. Configured as an error in .editorconfig. Shared IChange detection moves into HarmonyChangeTypes, used by both rules. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…n-8fb653' into claude/analyzer-non-deterministic-calls-57a179
|
No actionable comments were generated in the recent review.
|
AI summary
Summary
Harmony replays every change on every client (and again whenever snapshots are regenerated). A fresh Guid or clock read inside a change type during replay gives each client its own value, which shows up as sync divergence rather than an error. The example sentence JSON patch did exactly that; #2813 fixes it, and this PR adds analyzer rule LX0002 so the next one fails the build instead.
Deny list (matched by declaring type + member name, so members missing on a TFM never match):
GuidNewGuid,CreateVersion7DateTimeNow,UtcNow,TodayDateTimeOffsetNow,UtcNowTimeProviderSystem,GetUtcNow,GetLocalNow,GetTimestampRandom,RandomNumberGenerator,Stopwatch,EnvironmentPathGetRandomFileName,GetTempFileNameDeliberate exceptions can be suppressed with
#pragma warning disable LX0002plus a justification.Evidence
LcmCrdtondevelopwith the rule reports exactly one error, at the originalGuid.NewGuid()inJsonPatchExampleSentenceChange.ApplyTranslationOp, and nothing else (theGuid.NewGuid()/DateTimeOffset.UtcNowuses in the create-change constructors are correctly exempt).After: stacked on Add major FW Lite CRDT model version to regenerate snapshots #2813, which replaces that call with a deterministic translation,
LcmCrdtbuilds with 0 errors.LexboxAnalyzers.Tests: 24 passed (9 existing LX0001, 15 new LX0002), covering the helper-method shape of the original bug, initializers, lambdas/local functions/method groups, nested helper types, abstract bases, constructor exemption, deterministic members of the banned types,nameof, no-Harmony compilations, and generated code.Merge Danger
Door: two-way
Build-time only; no runtime code changes. Revert the rule or lower the severity in
.editorconfigto walk it back.Blast Radius: build
Any backend compilation that references Harmony. Today nothing outside
LcmCrdt/ChangesimplementsIChange, and after #2813 that directory is clean, so no existing code is flagged.Test plan
dotnet test backend/Analyzers/LexboxAnalyzers.Tests— 24 passeddotnet build backend/FwLite/LcmCrdt/LcmCrdt.csprojondevelopflags only the knownGuid.NewGuid()line; on this branch (merged with Add major FW Lite CRDT model version to regenerate snapshots #2813) it builds with 0 errors🤖 Generated with Claude Code