Spent a couple hours troubleshooting some gremlins. My patterns were freezing after a few seconds of working properly. My codebase has some interrupts and is a little complicated, conceptually, so I stripped a lot of that code out, gradually, and in the process found absolutely no difference in how the thing was failing.
Turns out, this thing really eats batteries. That's no surprise, considering the quantity of LEDs, especially blue ones.
On power-up, voltage is nominally 4.5V, my PIC starts up and starts sending patterns to the driver chips.
After a few seconds of normal operation, this extra power draw causes the battery voltage to sag, browning out my microcontroller.
The driver chips don't turn off. They're not receiving any data, but they're otherwise working, so they just hold position. Meanwhile, they're keeping enough LEDs on that the microcontroller stays browned out, and never successfully recovers.
After getting suspicious and popping a few new batteries in, everything works great again.
PICs have a brown-out detection peripheral, but I've never had cause to look into how it works before. I guess I'll delve into it soon and add some user notification of some sort.