The mystery of the undead sprites is solved!

As it turns out, a line in the Sprite constructor I wrote so long ago automatically adds sprites to their SpriteList upon construction. Forgetting this, I always added Sprites a second time every time they were created everywhere else in the code, which meant that trying a remove() on them only deleted one of the two references in the SpriteList (and since the Sprite was already kill()-ed, it would not try to remove the other one).

It was simplest to just remove that line from the Sprite constructor, so that's what I did. Now bullets disappear when they are supposed to.