Every set-fold cell now renders a phrase no other rule and no page chrome can produce, so one assertion pins exactly one rule.
11 Sept 2026 · branch ui-db-d0-evidence-assertions · captured against propflow-stage · at 716c077a6f
Data note. Every name and balance below comes from propflow-stage, which is anonymized by construction (ADR-0097/0110 — phones in the impossible +1000 NPA, emails @example.test). The identical capture against prod would carry real tenants' names and balances and is not safe to attach anywhere, which is why the generator refuses to run against one.
The Spec block gains a set fold column — the setRule DB-D0 puts on every catalogue entry. Occupancy is the number the design page works its example out on, and it is the one most easily got wrong: a 100 %-occupied four-unit building beside a 50 %-occupied 120-unit building is 51.6 %, and averaging the two rates says 75 %.
So the cell does not stop at the rule name. For a weighted_ratio it prints the arithmetic — Σ occupiedUnits ÷ Σ totalUnits — because the rule name tells a reader the shape of the answer while the part keys tell them which numbers actually get added, and that is the half that goes wrong.
Both part keys are new catalogue entries in this PR. They were on the stats payload already and were never written to the daily row, which is why a multi-property roll-up had no numerator and no denominator to fold and dropped occupancy entirely rather than fabricate it.
Asserted in the captured DOM — Occupancy Rate · SET FOLD · weighted_ratio · Σ occupiedUnits ÷ Σ totalUnits. The rule AND both named parts, as one distinctive string only this cell can produce. The column header renders UPPERCASED, so the assertion is 'SET FOLD' — the string a reader actually sees.
occupiedUnits is not a private field of the occupancy rate — it is a metric with its own spec, its own daily row and its own fold rule. That matters: a weighted ratio is Σ numerator ÷ Σ denominator, so the parts have to be summable in their own right, and the drift guard in this PR refuses a weighted_ratio whose parts are not sum.
Asserted in the captured DOM — Occupied Units · SET FOLD · sum · Σ across the set. Asserts the CELL, not the route. The old spec checked 'occupiedUnits', which is in the URL and therefore on the page whether or not the cell rendered — a check that could not fail. 'sum · Σ across the set' can only come from the set-fold cell.
The denominator gets the same treatment. Its description carries the rule the fold enforces: a zero here is the “no tenants in scope” dash, never a 0 % occupancy — the two say opposite things to a property manager and only one of them is true.
Asserted in the captured DOM — Total Units · SET FOLD · sum · Σ across the set. Same fix, same reason. The note now says exactly what the array checks: the denominator's own row renders the sum rule. It previously claimed 'both halves of the ratio fold by sum' while asserting neither — a description of a check that was not performed, inside the artifact whose whole job is to make that impossible.
Not every rate can be folded from stored numbers. delinquencyRate's numerator and denominator are not on the payload or the daily row, so it is marked recompute — the sixth rule's honest answer: the server ships {num, den} per org and the fold happens above, and a part that arrives without them is refused by name rather than quietly dropped.
What it is emphatically not marked is sum or mean. The drift guard fails on any rate-kind entry carrying either.
Asserted in the captured DOM — Delinquency Rate · SET FOLD · recompute · {num, den} shipped per org. 'recompute' alone was a bare token; the full phrase is what the cell produces and what distinguishes it from weighted_ratio on screen.
The first artifact asserted occupiedUnits and totalUnits on blocks 2 and 3. Both strings are in the ROUTE (?path=metrics/occupiedUnits), so they were on the page whether or not the set-fold cell rendered at all — the assertions could not fail, which is worse than not asserting. The durable fix was on the producer rather than the spec: describeSetFold now gives every rule a phrase that no other rule and no page chrome contains, pinned by a unit test that checks distinctness AND non-containment. Every block now asserts its own cell.