I will speculate on what is happening here.
One comment applicable to all three cases is that none of the models involve states or memory. So the only thing the solver needs to worry about is when certain events will occur and what action to take at those times. Also, using the default Nonadaptive zero crossing algorithm.
I'm going to consider the three cases in reverse order.
1-Step: The Pulse Generator has Variable Sample Time, which means "the block tells Simulink when to run it."
From t = 0, the solver has to figure out how far to take the next step. The candidates are t = 0.05 (trailing edge of the first pulse, which the block tells the solver) or t = 0.5 (max step). So it initially takes the smaller of the two t = 0.05. The solver can then do a final check to make sure that it didn't miss anything, like a zero crossing event. There are none, so it stays at 0.05.
From t = 0.05, going through the same process, it takes the max step to t = 0.55.
From t = 0.55, the choices are either step to t = 1, or t = 1.05. So it picks t = 1 as the candiate. At that time, it detects the hit crossing. So the question for the solver is whether or not it needs to go backwards to figure out when that crossing really occurred. I'm going to speculate it doesn't, beacause the Variable Sample Time of the root source block is telling the solver that nothing would have changed prior to t = 1. So it keeps the step at t = 1 and sets the Hit Crossing output high.
From t = 1, the solver determines that the next event is not earlier than t = 1.05 (trailing edge of the pulse). So it jumps to t = 1.05, at which point the hit crossing output goes low.
2-Step: The Clock has Continuous Sample Time.
From t = 0, solver takes the max step t = 0.5, no problem.
From t = 0.5, solver takes the max step to t = 1, no problem.
From t = 1, solver tries to take the max step to t = 1.5. Detects the hit crossing occured somewhere between t = 1 and t = 1.5. Now it has to go backwards. I don't have a clue how that NonAdaptive algorithm works, so don't know why it couldn't figure out that the threhold was reached at t = 1/0.9 (in general, finding the exact time of the crossing won't be so easy). In any case, it backs the solver up to t = 1/0.9 - eps (out.tout(4)), which is as close as it can get to the crossing. Maybe it purposefully tries to bracket the crossing point?
From t = 1/0.9 - eps, the solver knows that the next step should be small to get on the other side of the hit crossing. For whatever reason, it took a step of 64*eps
At this point, the input to the Hit Crossing at out.tout(5) exceeds the threshold, and the input at out.tout(4) is below, so it sets the output high. As required, the block found the hit crossing, to within some tolerance (over which the user has not control as far as I can tell for the NonAdaptive algorithm.
From t = 1/0.9 + 63*eps, the solver is free take the max step, because there is no reason not to.
BTW, I changed the min step size of the solver to 100*eps, and got the exact same result with no warnings or errors. Not sure what that's all about. Maybe the min step size doesn't apply for zero crossing algorithm.
3-Step Case: This case is the same as the 2-step case up to the point of out.tout(5) = 1/0.9 + 63*eps.
From t = out.tout(5) = out.tout(4) + 64*eps = 1/0.9 + 63*eps. Now the solver has to decide what its next step should be. My first thought was that it should try the max step as a candidate and see if any events occurred prior. But it doesn't do that. Instead it takes a step of 64*eps again (u is the input to the hit crossing and y is the output)
>> [out.tout out.u>=1 out.y]
0 0 0
5.000000000000000e-01 0 0
1.000000000000000e+00 0 0
1.111111111111111e+00 0 0
1.111111111111125e+00 1.000000000000000e+00 1.000000000000000e+00
1.111111111111139e+00 1.000000000000000e+00 0
1.611111111111139e+00 1.000000000000000e+00 0
2.000000000000000e+00 1.000000000000000e+00 0
My speculation is that the solver takes this small step because it can't predict when the next event will occur because of the Continuous Sample Time of the clock AND because there might be a customer of the output of the Hit Crossing. So it takes a small step and gives us the spike output. Assuming that's what's really happening here, I don't know if that's an intentional feature or not. But if it is, it is useful.
I did some additional experimentation that suggests the solver is smart enough to know that the function driving the hit crossing is Variable Time, even if the actual solver step size is being determined by other factors, like a small time constant filter. The solver even knows this if there is gain block between the Pulse Generator and the Hit Crossing, where the sample time of the output of the gain block is FiM.
Summary: If the ultimate signal driving the hit crossing is Continuous Sample Time and the Hit Crossing has an output, you get the 3-step case with one very small step prior to the Hit and one very small step after the Hit, with the output being 0-1-0 at those times. That seemed to be true with other inputs, as long as the hit crossing was detected (see Note below).
Disclaimer. This is all just guesswork.
Note: It's also easy to miss the hit crossing altogether. Go back to the 1-Step case and replace the Clock with a Sine Wave block with Amplitude 2 and Frequency 2*pi/0.5.