An options map for the resolvers, and sid beside the clip it is in

Finishing the last commit, which traded a simpler definition for noisier call
sites: deleting the arity ladders left `(symbol/resolver sym st pal/index-of
nil nil)` at twenty-odd places, and two trailing nils tell a reader nothing
except to go and count positions.

The ladder was a symptom. The disease is five positional parameters, and the
split that matters is which of them are OPTIONAL:

  store, palette    positional, because neither is optional. A dense channel
                    cannot be read without the store it names — that is the
                    crash two commits ago — and every op carries a colour.
  pose-tracks       one call site, in `clip/resolver`'s own recursion
  source/picture-fps  two call sites

So the last three become one `opts` map, and the common call loses a nil. The
point is not the nil: it is that the sixth option, whenever it arrives, is a
key at one call site rather than a nil at fifty.

`clip/resolver` also had `sid` FOURTH, behind two arguments that say nothing
about which symbol is being resolved. It is second now, beside the clip it is
in: `(clip/resolver c :main store pal/index-of nil)`.

62 call sites rewritten by parsing the forms rather than by regex, because
`clip/resolver`'s arguments move past each other and a regex cannot see that.
An earlier attempt at this dropped `palette` on the floor and still compiled
at 62 sites — it only surfaced as an arity error, so if that had been a
same-arity mistake the tests would have been the last line of defence.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Your Name 2026-09-30 12:21:12 -04:00
parent ee66680a0c
commit 624242b407
20 changed files with 84 additions and 81 deletions

View file

@ -36,7 +36,7 @@
:channels {[:xform :pos] (ch/framed [120 50])}}}})
(assoc-in [:symbols :sym/test]
(assoc (get-in source [:symbols :main]) :id :sym/test)))
resolve (clip/resolver document nil pal/index-of :main nil)
resolve (clip/resolver document :main nil pal/index-of nil)
at (fn [f] (mapv (juxt :node :cx) (resolve f)))]
(is (empty? (clip/problems document)))
(is (= [[[:left :mark] 110]] (at 1)))
@ -75,9 +75,9 @@
:parent :root :z "a2"
:playback {:tracks {:mouth {0 0, 8 8}}}}}}
:sym/poses symbol}}
resolve (clip/resolver document {"sizes" {:data values}} pal/index-of :main nil)
low-resolve (clip/resolver document {"sizes" {:data values}}
pal/index-of :main {:picture-fps 8})
store {"sizes" {:data values}}
resolve (clip/resolver document :main store pal/index-of nil)
low-resolve (clip/resolver document :main store pal/index-of {:picture-fps 8})
at (fn [f] (into {} (map (fn [op] [(:node op) op])) (resolve f)))
low-at (fn [f] (into {} (map (fn [op] [(:node op) op])) (low-resolve f)))]
(is (empty? (clip/problems document)))
@ -98,14 +98,12 @@
"an explicit cut occurs at its exact local frame, even off the picture grid")
(is (= 8 (:cx (get (low-at 8) [:first :eye])))
"authored position ignores the picture grid")
(let [sym (get-in document [:symbols :sym/poses])
opts {:source-fps 30 :picture-fps 8}]
(let [sym (get-in document [:symbols :sym/poses])
opts {:source-fps 30 :picture-fps 8 :pose-tracks {:mouth {0 0, 8 20}}}]
(is (= (mapv #(select-keys % [:node :cx :size])
(symbol/eval-frame sym 8 {"sizes" {:data values}}
pal/index-of {:mouth {0 0, 8 20}} opts))
(symbol/eval-frame sym 8 store pal/index-of opts))
(mapv #(select-keys % [:node :cx :size])
((symbol/resolver sym {"sizes" {:data values}}
pal/index-of {:mouth {0 0, 8 20}} opts) 8)))
((symbol/resolver sym store pal/index-of opts) 8)))
"pure evaluation and playback apply the same pose choice"))))
(deftest stage-pose-edits-preserve-earlier-motion-and-survive-save