In the course of trying a few things, I discovered I didn't even need to call the function to create the problem. I could just have the line
seeds[my_index] = 5;
and my spin_out would contain all 5s.
If I comment out the assignment to seeds[myindex], then spin_out contains whatever I assign to it. (I tried values other than 0 to rule out the usual sorts of problems that come from 0 being a default value for a lot of things).
Since I can get spin_out to return the correct value when the assignment is commented out, that increases my confidence that I'm reading the right buffer and that I'm passing my args in the right order (and I've checked them multiple times.)
Changes in the calling code inadvertantly led to the args to Enqueue2DRangeKernel to incorrect dimensions. The second dimension was too high by a factor of 16, which resulting in the buffers overwriting their boundaries.