Change:
becoming idle.  Non-ack-eliciting packets are eventually acknowledged when the endpoint sends an ACK frame in response to other events. <ins> An endpoint that is only sending ACK frames will not receive acknowledgments from its peer unless those acknowledgments are included in packets with ack-eliciting frames.  An endpoint SHOULD send an ACK frame with other frames when there are new ack-eliciting packets to acknowledge.  When only non-ack-eliciting packets need to be acknowledged, an endpoint MAY choose not to send an ACK frame with outgoing frames until an ack-eliciting packet has been received. An endpoint that is only sending non-ack-eliciting packets might choose to occasionally add an ack-eliciting frame to those packets to ensure that it receives an acknowledgment; see ack-tracking.  In that case, an endpoint MUST NOT send an ack-eliciting frame in all packets that would otherwise be non-ack-eliciting, to avoid an infinite feedback loop of acknowledgments. </ins> In order to assist loss detection at the sender, an endpoint SHOULD generate and send an ACK frame without delay when it receives an ack- eliciting packet either:

Discussion:
There is a little connective tissue added here to connect to the ACK tracking thing.
NAME -- ptal when you get a chance
In the Loss Recovery Pseudocode, is initialized to 0: URL This can result in dividing by zero if one implements a Cubic congestion controller () that incorporates (as the ). Cubic specifies the , used in congestion avoidance, as: An endpoint can enter congestion avoidance without receiving any acks for any ack-eliciting packets (only non-ack eliciting packets). In such a scenario, would still be 0, due to the requirement from : Since is 0 when is calculated, the divide by 0 occurs. This could be addressed by initializing to instead of 0.
FWIW this was changed from back to 0 in URL
I feel the existing pseudocode is ok, because minrtt in the text and pseudocode is used for the purpose of rejecting potentially bad RTT samples, and is not a general purpose minrtt. URL For example, BBR uses a windowed min_rtt that's fairly different. This does bring up an edge case I hadn't thought much about, where no ack-eliciting packets are acknowledged, but a packet is declared lost. A compliant transport implementation shouldn't ACK only ACK-only packets, but a non-compliant one could.

This does bring up an edge case I hadn't thought much about, where no ack-eliciting packets are acknowledged, but a packet is declared lost. A compliant transport implementation shouldn't ACK only ACK-only packets, but a non-compliant one could. The situation we saw was under severe packet loss, the peer sending probe packets containing a PING and ACK for non ack eliciting packets (ACKs and PADDING). The ACK-eliciting packets we send are getting dropped, so eventually we declare an ACK-eliciting packet lost and enter Recovery. When the next ACK comes in for a packet sent after we entered Recovery, we enter Congestion Avoidance and experience the issue with .
I'm still a bit unclear. Under what circumstances would a compliant peer send an ACK that only acknowledges non ack-eliciting packets?
After a probe timeout. Would that be non-compliant?

In regards to the issue originally raised about minrtt, I still feel the minrtt is not general purpose, so the originally stated issue is not a problem in the context of QUIC recovery. Other discussion follows. First, you'd have to complete the handshake without an RTT sample, which seems unlikely, but possible, so let's assume that. A PTO would send an ack-eliciting packet, and when the ACK for that packet came back, you'd have an RTT sample. However, if the peer was sending ACK+PING for every other ACK+PADDING packet, then you're correct that the incoming ACK bundled with the PING would not create an RTT measurement, but would allow any previously sent ACK-eliciting packets to be declared as lost if the packet threshold was reached. In regards to "peer sending probe packets containing a PING and ACK for non ack eliciting packets (ACKs and PADDING)", if you're saying that the peer is sending those in response to every ACK+PADDING packet, that sounds non-compliant to me. In regards to whether it's ok to send ACK+PING in response to ACK+PADDING, I re-read "Sending ACK Frames"(URL) and it says: "An endpoint MUST NOT send a non-ack-eliciting packet in response to a non-ack-eliciting packet, even if there are packet gaps that precede the received packet." Are you sending PADDING+PING due to that prohibition? I'm a bit concerned that could cause an infinite or near-infinite loop under the wrong circumstance, which was exactly the issue the paragraph highlights. The last paragraph does specifically preclude sending ack-eliciting packets in response to every non-ack-eliciting packet: "A receiver MUST NOT send an ack-eliciting frame in all packets that would otherwise be non-ack-eliciting, to avoid an infinite feedback loop of acknowledgments." It may make sense to move that final paragraph up, as it's a bit disconnected at the moment?
Agree that its not a problem within the context of QUIC recovery, I just wanted to call it out as an issue I experienced. If there wasn't much reason to initialize to 0 perhaps initializing to a value that is actually possible would make sense (and would prevent issues like the one I saw), but its not a big deal.

Just to clarify, only the peer is sending PINGS in the scenario we saw (actually PADDING+PING+ACK) The peer is sending ack-eliciting packets (PADDING+PING+ACK) due to PTO timeouts, its not a case of upgrading non-ack-eliciting packets to ack-eliciting by throwing in a PING every time, more that the ACKs are getting included when the probes get sent. I did find this paragraph confusing until I read URL, I'm not sure moving it up would help without some additional rewording.
LG, one possible suggestion to a sentence I've been confused by before.