Change:
13.1.1. <del> An endpoint MUST NOT send more than one packet containing only an ACK frame per received packet that contains frames other than ACK and PADDING frames.  An endpoint MUST NOT send a packet containing only an ACK frame in response to a packet containing only ACK or PADDING frames, even if there are packet gaps which precede the received packet.  This prevents an indefinite feedback loop of ACKs.  The endpoint MUST however acknowledge packets containing only ACK or PADDING frames when sending ACK frames in response to other packets. </del> <ins> An endpoint sends ACK frames to acknowledge packets it has received and processed. Packets containing only ACK frames are not congestion controlled, so there are limits on how frequently they can be sent.  An endpoint MUST NOT send more than one ACK-frame-only packet in response to receiving an ACK-eliciting packet (one containing frames other than ACK and/or PADDING).  An endpoint MUST NOT send a packet containing only an ACK frame in response to a non-ACK-eliciting packet (one containing only ACK and/or PADDING frames), even if there are packet gaps which precede the received packet.  Limiting ACK frames avoids an infinite feedback loop of acknowledgements, which could prevent the connection from ever becoming idle.  However, the endpoint acknowledges non-ACK-eliciting packets when it sends an ACK frame. </ins> Packets containing PADDING frames are considered to be in flight for congestion control purposes QUIC-RECOVERY.  Sending only PADDING

Discussion:
MUST NOT bundle a PING with all packets that would otherwise be ACK-only. If there's anything else discussed in London that I missed, please tell me.
Isn't this just moving up one level in the inception layer? Now you must not send ACK+PING too often to prevent an indefinite feedback loop? Why not just say that an ACK should not ACK / PAD only frames for more than a fraction of the packets to avoid feedback loops and to ensure eventual reduction of gap accounting?
NAME My past experience has been that it's better if the sender of ACKs is in control of how often they want an ACK in response. There are a number of packet tracking/ACKing algorithms which never require ACKs of ACK-only packets, and I think we should accommodate those. Making the receiver of ACKs guess how often to ACK ACKs is a problem that's impossible to get right, and as NAME said on the issue, one can never rely on any receiver behavior regarding when they'll ACK ACKs, so it's more robust if the sender is in control. I will add normative text about not including a PING with every ACK.
OK, that makes sense.
I've now removed ACK-only from the transport text, and replaced it with ACK-eliciting.
The transport spec says in section 13.1.1: "An endpoint MUST NOT send a packet containing only an ACK frame in response to a packet containing only ACK or PADDING frames, even if there are packet gaps which precede the received packet. This prevents an indefinite feedback loop of ACKs." I argue that this MUST NOT should be changed to SHOULD NOT. Fist, the infinite feedback can be prevented if, for example, an implementation only sends an ACK for N packets received, so there is really no need to be that strict. Second, ACK of ACK are generally useful. They enable trimming the grow of ACK lists in a controlled way. In fact, I found that problem in interop tests. Some implementations would send thousands of data packets without sending a single ACK of ACK. That means the sender is stuck with a large ACK dashboard. Yes, it could be trimmed with timers, but that's hardly a controlled process. I fixed this by sending an ACK + PING packet whenever there the unacked ACK list is too long, but that's a hack.

I'd argue that ACK+PING isn't a hack, but instead a simple way for the sender, whose state we're trying to limit, to balance the amount of state it stores vs the extra ACKs being received. Getting the peer to implement the correct ACK behavior by sending a single extra byte is much simpler and more robust in my experience than relying on the receiver to implement an "ACK every 10/20/etc ACKs" policy in a way that every sender is happy with. This could likely use more text and there's still an outstanding editorial issue to move most of the ACK sending text that's in recovery into transport, so it's all in one place, since I believe there are currently a few subtle inconsistencies.
Completely agree. Ian hits on the key point here. In the case of an endpoint that would like to limit the amount of state it stores, it's highly desirable for THAT endpoint to be in control. ACK+PING, satisfies that. Relying on ACKs of ACKs from the peer does not, sadly.
Agreed with NAME Irrespective of what we recommend here, note that a sender of ACKs cannot assume what the peer will do -- when the peer will send an ACK for ACKs, I mean -- so, it will end up having to send a periodic PING anyways. Piggybacking a PING periodically (once an RTT, for example) is useful for RTT measurement as well, since ACK of ACKs do not get used for RTT (see for more discussion on this point).
An alternative would be allowing sending ACKs-of-ACKs, if you are sending non-(ACK|PADDING) frames. So, maybe: "An endpoint MUST NOT send a packet containing only ACK or PADDING frames in response to a packet containing only ACK or PADDING frames, if the previous packet it sent contained only ACK or PADDING frames."
As discussed in London, NAME to write a PR with some advisory text
So many comments, so much opportunity for this to get worse if we don't stop.Minor nit, but looks good.Text looks good, just noticed a few minor whitespace nits while reading through.