Files
recordingtest/docs/contracts/normalizer-followups.evaluation.md
minsung 2428827df6 Orchestrate normalizer follow-ups evaluation + update PROGRESS
- Float epsilon configurable (default 6) pass
- JSON-path mask scoping pass with regression trap verified
- 77/77 tests, 3 follow-ups marked done

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 20:45:04 +09:00

3.5 KiB

normalizer-followups — Evaluation

Verdict: PASS Generator commit: eeee3c2 Evaluator date: 2026-04-07

Verdict table

# Criterion Evidence Result
1 dotnet build recordingtest.sln — 0 warn / 0 err Build succeeded, 0 Warning(s), 0 Error(s) pass
2 dotnet test total 77 pass 16+17+16+5+5+6+6+6 = 77 passed, 0 failed pass
A1 Profile.FloatDecimals int? with YAML alias float_decimals Profile.cs:14-15 [YamlMember(Alias="float_decimals")] public int? FloatDecimals pass
A2 RoundFloatsInNode accepts decimals parameter Rules.cs:102 RoundFloatsInNode(JsonNode?, int decimals) + default overload using DefaultFloatDecimals pass
A3 DefaultFloatDecimals = 6 Rules.cs:97 public const int DefaultFloatDecimals = 6 pass
A4 Profile decimals flows via Normalizer Normalizer.cs:95 profile.FloatDecimals ?? Rules.DefaultFloatDecimals pass
A5 Omitted float_decimals defaults to 6 Test Profile_OmittedFloatDecimals_DefaultsTo6 asserts profile.FloatDecimals == null and output rounds to 3.141593 pass
A6 Configurable decimals actually applied Test RoundFloats_ProfileWithDecimals3_RoundsTo3 writes temp profile, expects 3.142 pass
B1 ParseJsonPathLite exists, rejects * and [...] Rules.cs:200-222 throws on wildcards/indexers, requires leading $. pass
B2 MaskVolatileSettings(node, paths) walks with path stack Rules.cs:227-289 pre-parses allowlist, maintains stack list, exact-chain compare in PathMatches() pass
B3 DefaultVolatileSettingPaths has 16 entries Rules.cs:176-194 — counted 16 paths pass
B4 default.yaml migrated to list form profiles/default.yaml:10-26 — YAML sequence of 16 $.<path> strings; float_decimals: 6 present pass
B5 Regression trap: SameNameInUnrelatedSubtree_NotMasked RuleTests.cs:174-183 — input {"GridSnap":true,"Foo":{"GridSnap":false}} with ["$.GridSnap"]; asserts root masked and n["Foo"]["GridSnap"].GetValue<bool>() == false. Pre-fix name-based fallback would have masked both, causing GetValue<bool>() to throw InvalidOperationException on <VOLATILE> string → test is load-bearing pass
B6 Nested path mask works MaskVolatileSettings_NestedPath_MasksCorrectly$.GridColor.R masks only R, leaves G pass
B7 Root mask works MaskVolatileSettings_RootField_Masks pass
B8 No leftover VolatileSettingFieldNames fallback Grep in src/ — no matches anywhere pass
9 CoverageTests still green Normalizer.Tests dll 16 passed (includes coverage tests) pass

Notes

  • Regression trap load-bearing: confirmed. The old VolatileSettingFieldNames.Contains(kv.Key) approach would mask both GridSnap occurrences → nested .GetValue<bool>() on a "<VOLATILE>" JsonValue would throw. The test would fail loudly.
  • Test count for Normalizer.Tests went from 10 → 16 as claimed (6 new tests present and accounted for).
  • Default-on behavior preserved: default.yaml both specifies float_decimals: 6 explicitly AND the omitted-profile test proves the ?? DefaultFloatDecimals fallback path.
  • Count of DefaultVolatileSettingPaths: 16 entries confirmed (CanOverrideWireColorWithFace, IsSidePanelVisible, OverrideFaceColor, Solar_IsLocalTime, VisibleGrid, GridSnap, MidpointOsnap, GridSpacing, GridColor.{ALPHA,BLUE,GREEN,RED}, MajorGridColor.{ALPHA,BLUE,GREEN,RED}).

Partial / gaps

None. Both follow-ups are complete with no residual fallback code.