Model's Debug renders its HashMaps in key order, so the effect fingerprints cannot flake (improvise-pc3b)

This commit is contained in:
Edward Langley
2026-09-23 08:15:57 -07:00
parent f85fddbb2f
commit 21e239dca5
4 changed files with 116 additions and 6 deletions
+16 -4
View File
@@ -495,10 +495,22 @@ compiler named every other consumer. Two remain, and both are the wire:
untouched.
One test consumer had to move: the effect-classification tests fingerprinted the
model and the views through `serde_json`. They now use `Debug`. That is no weaker:
it renders every field, including the derived `formula_cache` the JSON skipped.
`format_md` was rejected as the replacement, because it skips the virtual views
and sorts the data, so it would have been a weaker fingerprint.
model and the views through `serde_json`. They now use `Debug`. `format_md` was
rejected as the replacement, because it skips the virtual views and sorts the
data, so it would have been a weaker fingerprint.
The first version of this paragraph said `Debug` was "no weaker" because it
renders every field, including the derived `formula_cache` the JSON skipped.
**That was wrong (improvise-pc3b).** A derived `Debug` prints a `HashMap` in hash
order, and `recompute_formulas` clears and refills the cache. So a correct
`ViewOnly` effect such as `RebuildLayout` changed the fingerprint in 90 of 200
runs. The suite passed only because the fixture had no formulas, so the cache
was empty. `Model` now has a hand-written `Debug` that renders `formula_cache`
and `measure_agg` in key order. The fingerprint keeps every field, including the
derived one, and a refill in a different hash order is no longer read as a
change. `recomputing_formulas_leaves_the_model_fingerprint_alone` pins this.
`view_only_effects_leave_shared_state_alone` now runs over a formula-bearing
fixture, for the same reason.
`parse_number_cell` returns `CellValue::Error` naming the offending text rather
than a fabricated `0.0`. No token the current grammar admits actually fails