Mostly vibecoded, but Claude needed some manual help for the trickier bits. Also I had Gemini handle the quaternion-based rotation math because Claude couldn't quite get it and I didn't want to have to remember how that worked.
I wanted this so I could do stats for how often a solve will end up in a given partial state, but I haven't gotten that far yet.