Came across some info on
spindle.N.at-speed from this post:
forum.linuxcnc.org/21-axis/31786-motion-spindle-at-speed
the machine will only pause to wait for the spindle at speed signal before a cutting move. It will still perform any G0 moves then wait at the start of the first G1,G2... until the pin goes true. All non auto movement is unchanged (jogging, MDI...) Once the at speed signal goes true the machine will not pause again if it later goes false, unless a spindle speed change or start is commanded.
Based on that info, the next question is did the gcode block on line N45 actually execute, i.e. did the Z move to 21 as commanded, or not.
If Z did move to 21 then the code is halting before the following G1 feed command, which adds weight to your theory.
If line N45 did not actually execute, then
spindle.N.at-speed must not be the reason if it only stops feed moves.