Your description is mostly right:
"The first step, the push, simply propagates a flag downstream to indicate that plugs are dirty, or not up to date, and stops where the updated plug was changed."
Because the dirty flag is propagated downstream it stops when there's no more downstream plugs that are dependent on the one that was dirtied "and stops where the updated plug was changed" sounds like you're describing an upstream propagation.
"When that happens the new data from the updated plug is pulled through the nodes to the new connection or query ( updating the dependencies along the way)."
This is correct but I thought I'd offer some extra detail. When a plugs values is queried (for drawing an object, displaying something in and editor, or because you used getAttr or another query command) if the plug is dirty then Maya will call the "compute" method of that node. The compute method takes the plug being computed as the input, and based on what output plug you are computing it will need to get the values of some input plugs. For example if Maya requested an addDoubleLinear.output plug, the compute method would get the values of input1 and input2 so it can add them to produce the output. If the inputs the compute method needs are dirty then it moves up in the DG graph to compute those inputs. It keeps doing this (setting the values it computes as clean as it goes) until it can compute the requested plug using clean values.
One little nuance that you might already know but I'll mention here in case someone with the same question finds this post in the future, is that Maya only computes the plugs that are requested, when you recompute an upstream plug Maya doesn't compute all the downstream plugs, only the ones that were requested.

There are some additional tidbits when you are in Parallel evaluation instead of DG, but that's beyond the scope of your question.