Ok I've figured this out but I'm not sure if its a bug or a "feature" the issue is that in stage #2 I was also setting:
proxy_set_header X-Bytes-Sent $body_bytes_sent;
This appears to cause $body_bytes_sent to be evaluated and "stored" so that subsequent uses of $body_bytes_sent don't call the method ngx_http_variable_body_bytes_sent to determine the amount of body bytes sent but instead uses the already stored value, which is now out of date.
In this case the solution is to not set X-Bytes-Sent to $body_bytes_sent in previous phase of the request, however there may be other cases where this is not possible, and where dynamic variable is required instead of a static one.
Looking through the source the fix for this could be to set NGX_HTTP_VAR_NOCACHEABLE for body_bytes_sent?