Change:
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.

Discussion:
any of which it can use when sending packets.  When the endpoint wishes to remove a connection ID from use, it sends a RETIRE_CONNECTION_ID frame to its peer.  Sending a <del> RETIRE_CONNECTION_ID frame indicates that the connection ID won't be used again and requests that the peer replace it with a new </del> <ins> RETIRE_CONNECTION_ID frame indicates that the connection ID will not be used again and requests that the peer replace it with a new </ins> connection ID using a NEW_CONNECTION_ID frame. As discussed in migration-linkability, each connection ID MUST be

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

that other frames are sent in addition to PADDING frames to elicit acknowledgments from the receiver. <ins> An endpoint that is only sending ACK frames will not receive acknowledgments from its peer unless those acknowledgements are included in packets with ACK-eliciting frames.  An endpoint SHOULD bundle ACK frames 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 wait until an ACK-eliciting packet has been received to bundle an ACK frame with outgoing frames. An endpoint SHOULD treat receipt of an acknowledgment for a packet it did not send as a connection error of type PROTOCOL_VIOLATION, if it is able to detect the condition. </ins> The receiver's delayed acknowledgment timer SHOULD NOT exceed the current RTT estimate or the value it indicates in the "max_ack_delay" transport parameter.  This ensures an acknowledgment is sent at least

Strategies and implications of the frequency of generating acknowledgments are discussed in more detail in QUIC-RECOVERY. <ins> 13.1.2. </ins> To limit ACK Ranges (see ack-ranges) to those that have not yet been received by the sender, the receiver SHOULD track which ACK frames have been acknowledged by its peer.  The receiver SHOULD exclude already acknowledged packets from future ACK frames whenever these <del> packets would unnecessarily contribute to the ACK frame size. Because ACK frames are not sent in response to ACK-only packets, a receiver that is only sending ACK frames will only receive acknowledgements for its packets if the sender includes them in packets with non-ACK frames.  A sender SHOULD bundle ACK frames with other frames when possible. </del> <ins> packets would unnecessarily contribute to the ACK frame size.  When the receiver is only sending non-ACK-eliciting packets, it can bundle a PING or other small ACK-eliciting frame with a fraction of them, such as once per round trip, to enable dropping unnecessary ACK ranges and any state for previously sent packets.  The receiver MUST NOT bundle an ACK-elicing frame, such as a PING, with all packets that would otherwise be non-ACK-eliciting, in order to avoid an infinite feedback loop of acknowledgements. </ins> To limit receiver state or the size of ACK frames, a receiver MAY limit the number of ACK Ranges it sends.  A receiver can do this even

the receiver SHOULD repeatedly acknowledge newly received packets in preference to packets received in the past. <del> An endpoint SHOULD treat receipt of an acknowledgment for a packet it did not send as a connection error of type PROTOCOL_VIOLATION, if it is able to detect the condition. 13.1.2. </del> <ins> 13.1.3. </ins> ACK frames MUST only be carried in a packet that has the same packet number space as the packet being ACKed (see packet-protected).  For