Reduction logic for squashing chord

PR a day. This is just the reduction logic, with an attempt to share what I can with the snapshot squash.

The most significant omission here is punting on the state/cache management of the reductions, which is going to require some more thinking. This would probably be handled elsewhere anyway, but that will be my task for tomorrow.
At one point I was tempted to store `i` in `SquashChordReducerEntityState` just for the hell of it, but then thought that might be overkill. Thoughts?