pub fn validate_tree(tree: &PatchTree) -> Result<(), String>Expand description
Every ceiling a hand-built patch has to respect, in one callable place.
apply_struct_op has always enforced these on its way out. The whole-tree
replace route (the wasm edit_set_tree, which is what undo/redo and every
client-side rewrite go through) never did — and that is precisely the route
a graph editor uses for move/reconnect. A forty-node hand-built patch is not
merely large: it sits outside the range the standardizer was fitted on, has
~zero mass under the prior, and the next refinement mutates it straight back
inside these ceilings, so the structure the player built by hand evaporates
the first time they press evolve, silently. Same ceilings, both routes.
Takes a shared reference — a caller validating a tree does not necessarily
own it — and pays one clone of a ≤24-node term for it, because the mod-depth
walk reuses the _mut accessors that already know which productions carry a
slot rather than standing up a second copy of that table to drift.
Also the parameter-domain predicate. It used to speak only about size
and depth, which left the one thing a term can be wrong about that no other
gate looked at: a value. amp.sustain = 1e30 walked through this function,
through finish(), into φ, into the exported PNG and into the persisted
observation log, and every surface downstream reported it as a number
(“SUSTAIN 1200.0 dB”) because none of them had been told what a knob’s range
is. Now they have, once, at crate::PARAM_DOMAIN.