diff --git a/context/adr/009-incremental-evaluation.md b/context/adr/009-incremental-evaluation.md index 33e43cfe..44aeadcb 100644 --- a/context/adr/009-incremental-evaluation.md +++ b/context/adr/009-incremental-evaluation.md @@ -189,6 +189,22 @@ an **edge adapter**. So every edge has the same semantics: defined in `improvise-protocol`. The adapter converts to and from it, and `zset` stays free of serde. `CellKey` is not `Serialize`, so on the wire a cell is named by its tuple of ids, its position or an ADR 002 surrogate. +- **The wire form is lossless.** Nothing is lost in transport, numeric precision above + all: + - a number never crosses as a JSON or JS double. A `numtower` `Num` crosses as its + canonical text (ADR 005). An f64 crosses as its exact bits, which keeps `-0.0` and + NaN payloads. That conflicts with today's `wire_f64` and with `numtower`'s `nan` + token, which both drop the payload, so the edge carries bits for every non-finite + value; + - integers wider than 2⁵³, including positions and counts, cross as strings; + - text crosses byte-exact, with no normalisation; + - the delta is the unit that crosses, never `ExactSum`'s limbs. A receiver that needs + a sum gets the host's exact read or rebuilds it from the exact deltas. + + The stamp rule detects lost messages, but nothing would detect a lossy encoding. So + every element type has a round-trip property test, where encoding then decoding is + the identity for every value, including `-0.0`, NaN payloads, 28-digit decimals and + `i128`-wide fractions. - **Stamps compose end to end.** The host stamps each published batch (below), and an intermediate edge forwards the stamp unchanged. So a loss anywhere on the path shows up downstream as a gap. @@ -245,8 +261,8 @@ maintained key, so it maps member keys through its own remap first. It then refe what moved. It refetches everything when it sees a publication gap, a new `document_generation` or host instance, its shape in the eviction list, or a notice it cannot read. A slow client may merge pending notices: the union of keys, the latest -stamp, and axis changes kept in order. Outputs are consolidated under the wire's value -identity, so every NaN counts as one value, because the wire spells every NaN `"nan"`. +stamp, and axis changes kept in order. Because the wire is lossless, outputs keep the +circuit's bit identity end to end. **What this replaces.** Today's per-session mirrors and pushed diffs (`Sessions`, `ClientSession`, `grid_updates`, `Projection`, `Dirty`). The host keeps no per-client