if i have a single ball in the cradle, the total mechanical energy is mostly conserved (friction = rollingFriction = angularDamping = damping = 0), though there is a slow decrease in time.
going back to just two balls, it does work for the first two or three collisions, but eventually energy is pumped into the system (restitution=1), ultimately resulting in some chaotic motion. the error initially shows itself by the colliding ball not having its velocity exactly zero. that is, isolated collisions are not handled exactly.
with more than two balls, if you introduce a slight gap between the balls in equilibrium, then the first two or three collisions behave as expected (and implies that simultaneous collisions is the main culprit). however, eventually a simultaneous collision occurs and energy can suddenly change.
it appears i need to replace/ignore Scenekit's physics simulation and implement my own. it's easy for this case, at least.