Merge dbsp/source-trait into dbsp/model-over-source

# Conflicts:
#	context/code/source.md
This commit is contained in:
Claude (dbsp-sources)
2026-10-10 19:31:46 -07:00
committed by Edward Langley
3 changed files with 142 additions and 32 deletions
+7 -4
View File
@@ -75,7 +75,8 @@ cells it never owns.
2. **A shared source changes behind its readers by interior mutability of its own.** The model holds
an `Arc`, so a database connection or a test double behind a lock is the same object the
backend feeds from.
3. **What still reads the owned store**: `get_cell`, persistence, the import wizard and the effects
3. **What still reads the owned store**: `get_cell` (a production caller: `improvise-command/src/ui/effect.rs`,
the `old` value of a rename), `Model::data` (`pub`), persistence, the import wizard and the effects
in `improvise-command`. They are the facade of a document that owns its cells; a model over a source
has none of those to offer, and routing them would change `get_cell`'s `&CellValue` return for 129
call sites. `Eager::occupancy`, `Shapes::of` and `Stems::build` in `improvise-incremental` are
@@ -93,6 +94,8 @@ lists, and two), at both widths and for all five functions: over 5,000 triples.
## Building a `Summary` from an engine's answer
`Summary::from_parts(Numbers::from_parts(count, exact_sum, least, greatest), Agreement)`. `Agreement`
is what the non-number values hold: `None`, `One(v)` or `Mixed`. `from_parts` drops extremes that
contradict the count or are NaN, so a source cannot hand the evaluator a state `add` could not reach.
`Summary::from_parts(Numbers::from_parts(count, exact_sum, least, greatest)?, Agreement)?`. `Agreement`
is what the non-number values hold: `None`, `One(v)` or `Mixed`. Both constructors return a `Result`
and **refuse** a state no sequence of values could produce (extremes with no numbers, a NaN extreme,
least above greatest, one extreme without the other, a number among the "others"), because repairing
it would hide an engine's bug.
+26 -6
View File
@@ -2314,6 +2314,11 @@ lost). The first two also fail `aggregating_differing_text_values_is_an_explicit
### model::source::tests::a_merge_of_summaries_is_the_summary_of_the_union
Review of #356 (Opus): the pool gained `1e16`, `1.0`, `-1e16`, `0.1` and `0.2`. A merge rounding each part's
sum before pooling, keeping the zero sign, changed 514 production answers while the workspace passed;
that rival now fails this test, `numbers_pool_what_the_formula_aggregate_pools` (a NaN-free split now,
compared as bits), `summaries_built_from_parts_merge_as_the_union_does` and the fixture test below, by name.
A read of several parts is a merge. The test merges every ordered pair of sequences of up to two
values and compares with the reference of the concatenation. Rivals: the least not merged, the
greatest merged with the other side's least, the zeros unordered. Each fails it.
@@ -2335,7 +2340,7 @@ span, and the store ignores `exact` for a spanned one. The first also fails
### model::source::tests::the_store_and_a_scanned_table_list_the_same_cells
`keys` and `cells` under every base of the fixture, and `value_at` for every row and an absent key.
Rival: `DataStore::keys` ignores its partial. It fails here and in five evaluator tests that read
Rival: `DataStore::keys` ignores its partial. It fails here and in seven evaluator tests that read
the member records of an aggregate over an expression
(`route_then_aggregate_tests::a_routing_formula_at_a_record_is_the_rule_itself` among them).
@@ -2384,13 +2389,28 @@ write goes to the owned store and nothing reads it.
### a_summary_built_from_an_engines_parts_reduces_as_one_built_from_the_values
Review of #356 (Codex): an engine outside core could not build a `Summary` without replaying rows. The
parts (count, exact sum, extremes, agreement of the non-numbers) are computed in the test without
`Summary::of`, for the 585 sequences of the reference test. Rivals: the greatest taken from the least;
a NaN allowed as an extreme. Each fails it.
parts are computed in the test without `Summary::of`, for every sequence of up to three values of the
pool. No rival of the first version failed this test alone (its filter was untested); see below.
### parts_that_contradict_themselves_are_made_consistent
### summaries_built_from_parts_merge_as_the_union_does
Extremes with no numbers, and a NaN as an extreme, are dropped by `Numbers::from_parts`.
A summary built from parts, merged with one built from values and with one built from parts, equals the
reference of the union, for every pair of sequences of up to two values. This is where a bad extreme
would matter, since merge reads the extremes.
### parts_no_sequence_of_values_could_produce_are_refused
Review of #356 (Opus, Codex): `from_parts` repaired some impossible states and accepted others
(`One(Number)`, least above greatest). It refuses all of them with a `BadParts` naming the reason.
The earlier entry's claim that a NaN-extreme rival failed `parts_that_contradict_themselves_...` was
false: that test passed with the filter removed. Rivals now, each failing this test alone: NaN extreme
allowed, least above greatest allowed, extremes with no numbers allowed, a number accepted among the
others.
### the_exact_sum_of_a_pool_of_cancelling_values_is_not_the_sum_of_rounded_parts
An exactness test needs inputs whose float sum is inexact and no NaN. `1e16 + 1.0 - 1e16` rounded part
by part is `0.0`; pooled exactly it is `1.0`. This pins the fixture rather than the code.
### keys_of_a_store_are_its_cells_keys_without_the_values