Keep one invalidation table, and derive the inverse a UI wants

There were two answers in the tree to "which stored bytes stop being valid when
this knob moves", and only one of them was checked.

`flow/address/block-knobs` is per block and asserted by biconditional —
`address-test` re-freezes the take once per knob and requires that the bytes
changed if and only if the key did. `domain/params`'s `:affects` was per area,
had no caller but a test asserting it returned what it was written as, and was
already wrong in both directions on the one entry where the two granularities
disagree: `:aperture-cut` claimed `#{:mouth}`, where it reaches no block, and
omitted the teeth, whose contour bytes it genuinely moves by gating
`condition/interior`'s smoothing. `:blink-cut` claimed `#{:eye}` and reaches no
block either, because a blink is `[:vis]` keys in tier 1.

So `:affects` and `affected-areas` are gone, and `address/knob-roles` is the
derived inverse of the table that is asserted — which is what a parameter panel
actually wants to ask. A knob absent from it invalidates no block, and that is
an answer rather than a gap.

Two new assertions keep the derivation from rotting at either edge: every role
in the table is reachable from some knob, and every knob a block declares is one
the registry defines. The second closes a real hole — `block-descriptor` checks
only that a knob was PASSED, and the freeze's `merge take/knobs` makes that true
of anything spelled like a keyword, so a typo in `block-knobs` would have named a
setting no slider can move.

228 CLJS tests, green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Olive Vaughn 2026-09-28 01:23:08 -04:00
parent 9cd5243983
commit 27bfe18bee
5 changed files with 85 additions and 13 deletions

View file

@ -204,6 +204,20 @@ bug waiting for a bigger project:
This table is the argument for the split, and it should be derivable from the
sub graph rather than maintained by hand.
As built, half of it is, by a different route. `flow/address/block-knobs` is this
table for tier 2 — per block, the settings its bytes depend on — and
`address-test` asserts it by biconditional rather than deriving it, which is
stronger than a derivation would have been: a derived table is only as right as
the graph it reads. What is not written down anywhere is the rest of the column.
Stages 3 to 5 are one call chain in `flow/take/measure` rather than a chain of
subs, so there is no graph above `::base-scene` to read a dependency off, and the
tier-1 half of a re-freeze is therefore whole-clip.
An earlier arrangement had a second table in `domain/params`, per feature area,
saying which areas a knob affected. It disagreed with the tested one on the first
entry where the two granularities part company and it had no caller; see that
namespace for why one checked table beats two.
| Knob | Invalidates from |
| --- | --- |
| model / footage | 2 detect |