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:
parent
9cd5243983
commit
27bfe18bee
5 changed files with 85 additions and 13 deletions
|
|
@ -26,9 +26,6 @@
|
|||
(is (= :person-4 (get-in scene [:features :eye-8 :subject])))))
|
||||
|
||||
(deftest parameter-definitions-drive-the-current-take-defaults
|
||||
(is (= #{:eye} (params/affected-areas :blink-cut)))
|
||||
(is (= #{:head :mouth :eye :brow :teeth}
|
||||
(params/affected-areas :anchor-avg)))
|
||||
(is (params/valid-settings? :eye {:blink-cut 0.2}))
|
||||
(is (not (params/valid-settings? :eye {:verts 8}))))
|
||||
|
||||
|
|
|
|||
|
|
@ -113,6 +113,31 @@
|
|||
(str "add " id " to block-knobs for " (pr-str role))
|
||||
(str "remove " id " from block-knobs for " (pr-str role)))))))))))
|
||||
|
||||
(deftest the-knob-inverse-is-derived-and-total
|
||||
;; `invalidates` is the parameter UI's question — "what stops being valid if I
|
||||
;; drag this" — and the reason it is derived rather than written down is that
|
||||
;; the thing it is derived FROM is the thing the biconditional above asserts.
|
||||
;; These two assertions are what keep the derivation honest in the only two ways
|
||||
;; it could rot.
|
||||
(testing "every role in the table is reachable from some knob"
|
||||
(is (= (set (keys address/block-knobs))
|
||||
(into #{} (mapcat val) address/knob-roles))))
|
||||
(testing "every knob a block declares is a knob the registry defines"
|
||||
;; The other direction of the same edge: a typo in `block-knobs` would name a
|
||||
;; setting no slider can move, and `block-descriptor` only checks that the
|
||||
;; knob was PASSED, which the freeze's `merge take/knobs` makes true of
|
||||
;; anything spelled like a keyword.
|
||||
(is (empty? (remove #(contains? params/definitions %)
|
||||
(into #{} (mapcat val) address/block-knobs)))))
|
||||
(testing "a knob that moves no bytes says so, rather than having no answer"
|
||||
;; Tier 1 knobs. Each one rewrites keys or a framed value on a re-freeze and
|
||||
;; no block's address changes, which is why the empty set is the right answer
|
||||
;; and not a missing entry.
|
||||
(doseq [knob [:blink-cut :iris-size :pupil-size]]
|
||||
(is (= #{} (address/invalidates knob)) (str knob)))
|
||||
(is (= #{"teeth"} (address/invalidates :aperture-cut))
|
||||
"the mouth's threshold reaches the teeth block and no other")))
|
||||
|
||||
(deftest the-teeth-table-is-asserted-at-the-descriptor
|
||||
;; Every knob the teeth block declares must reach its key. The other half — that
|
||||
;; each one also moves its bytes — needs real pixels, because the crop, the otsu
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue