jiebi/TextFlow huggingface dataset:
Original text:
Message by passing the same MessageContext, until the endOfMessage flag is delivered or a ReceiveError occurs.  All partial blocks of a single Message are delivered in order without gaps.  This event does <del> not support delivering discontiguous partial Messages. </del>  If the minIncompleteLength in the Receive request was set to be infinite (indicating a request to receive only complete Messages),

Reviewer comments:
says: What happens if a ReceivedPartial event is dispatched on an unreliably connection, but the rest of the message never shows up? Is it the case that another call to Receive will result in two events being sent: Received (or ReceivedPartial) for the new message, and a ReceiveError for the original message? Or can two messages effectively be interleaved and delivered in whatever order the constituent packets arrive?
Could you elaborate on the error case that's on your mind? Because it's unclear to me - I would say that ordering obviously needs to be preserved within a message, while inter-message ordering is a different issue (controlled by the msgOrdered Message Parameter). How is this not clear from saying that delivering discontiguous partial Messages is not supported?
Let's say you send the following: M1 M2 M3 N1 N2 N3 where M=M1.M2.M3 is one message and N=N1.N2.N3 is another message. The receiver subsequently gets: M1 N1 N2 N3 My reading of the draft is that the receiver will see ReceivedPartial ReceivedPartial ReceivedPartial Received If M2 and M3 subsequently arrive, it sounds like the receiver will never get ReceivedPartial or Received because "this event does not support delivering discontiguous partial Messages." But what makes the receiving TAPS logic decide not to wait for M2 or M3 and to start delivering N?
This is not how I would have interpreted the sentence. It talks about the message itself being discontiguous - so, e.g., delivering M1 followed by M3 would never happen. I don't see a reason why a different message couldn't be delivered, in pieces or not, after a ReceivedPartial call - every receive call comes with a message context, so the messages can be separated. I can try to make this clearer, maybe by adding an example like yours here to the draft....

Revised text:
Message by passing the same MessageContext, until the endOfMessage flag is delivered or a ReceiveError occurs.  All partial blocks of a single Message are delivered in order without gaps.  This event does  <ins> not support delivering discontiguous partial Messages.  If, for example, Message A is divided into three pieces (A1, A2, A3) and Message B is divided into three pieces (B1, B2, B3), the ReceivedPartial may deliver them in a sequence like this: A1, B1, B2, A2, A3, B3, because the messageContext allows the application to identify the pieces as belonging to Message A and B, respectively. However, a sequence like: A1, A3 will never occur. </ins> If the minIncompleteLength in the Receive request was set to be infinite (indicating a request to receive only complete Messages),
Original text:
attempts in parallel, "unconnected" protocols such as raw UDP do not offer a way to validate the presence of a peer or the usability of a Connection without application feedback.  An implementation should <del> consider such a protocol stack to be established as soon as a local route to the peer endpoint is confirmed. </del>  However, if a peer is not reachable over the network using the unconnected protocol, or data cannot be exchanged for any other

Reviewer comments:
My first try to make a PR from the web interface. Maybe this compiles without problems?
Aha, the error appears even when doing it over the web interface.
I think I am missing something ... how do endpoints know a route exists (is present)? My thinking from NEAT was that endpoints only knew this was established when there was some "confirmation" from the remote endpoint. Do you mean something else?
NAME this is for UDP, nothing is sent to the other end until the application sends data. it was the same in neat, our open call in neat just returned immediately for UDP.
True - for UDP, as you say, you basically know the Interface is up (and often not much more), but the words "established" sounds more like what happened when you get the first packet back... Maybe I could live with this, but it doesn't immediately inspire the right sense...
Yes, "connectivity is established" is not good at all, this is why I said the proposed update made it worse :) Or you mean that "local port reservations has been established" also triggers the wrong idea because of "established"? How about "... any necessary state like local port reservations is available/has been allocated." Or just remove that part all together.
In Sec 4.5 of taps-impl: "An implementation should consider such a protocol stack to be established as soon as a local route to the peer endpoint is confirmed." What does this mean for an unconnected protocol? That there is an entry in the route table, or that it's received a packet?
Good catch: This appears to be rough sentence. The term "confirmed" occurs only once, and a "local route" is something quite different to what is intended! We do talk about establishing connectivity with a remote endpoint... maybe that might work?

Revised text:
attempts in parallel, "unconnected" protocols such as raw UDP do not offer a way to validate the presence of a peer or the usability of a Connection without application feedback.  An implementation should  <ins> consider such a protocol stack to be established as soon as the Transport Services system has selected a path on which to send data. </ins> However, if a peer is not reachable over the network using the unconnected protocol, or data cannot be exchanged for any other
Original text:
Before an implementation marks a Message Framer as ready, it can also dynamically add a protocol or framer above it in the stack.  This <del> allows protocols like STARTTLS, that need to add TLS conditionally, to modify the Protocol Stack based on a handshake result. </del>  6.2.

Reviewer comments:
The implementation draft should explain that a framer can go into a passthrough/inactive mode once it has finished (like SOCKS, STARTTLS, CONNECT).

Revised text:
Before an implementation marks a Message Framer as ready, it can also dynamically add a protocol or framer above it in the stack.  This  <ins> allows protocols that need to add TLS conditionally, like STARTTLS RFC3207, to modify the Protocol Stack based on a handshake result. A Message Framer might also choose to go into a passthrough mode once an initial exchange or handshake has been completed, such as the STARTTLS case mentioned above.  This can also be useful for proxy protocols like SOCKS RFC1928 or HTTP CONNECT RFC7230.  In such cases, a Message Framer implementation can intercept sending and receiving of messages at first, but then indicate that no more processing is needed. </ins> 6.2.
Original text:
should not terminate an earlier child connection attempt upon starting a secondary child. <del> If a child node fails to connect before the delay time has expired for the next child, the next child should be started immediately. </del>  Staggered racing between IP addresses for a generic Connection should follow the Happy Eyeballs algorithm described in RFC8305.  RFC8421

Reviewer comments:
Section 4.2.2 says "If a child node fails to connect before..." without really defining if this means completing the handshake, or making some progress. 4.3.1 does a better job, but for readability there ought to be a reference or rewording in 4.2.2.
/to connect/ is problematic for me also, but /establish connectivity/ is less problematic, although always good to explain!

Revised text:
should not terminate an earlier child connection attempt upon starting a secondary child.  <ins> If a child node fails to establish connectivity (as in determining- successful-establishment) before the delay time has expired for the next child, the next child should be started immediately. </ins> Staggered racing between IP addresses for a generic Connection should follow the Happy Eyeballs algorithm described in RFC8305.  RFC8421
Original text:
Connection establishment is divided into two top-level steps: Candidate Gathering, to identify the paths, protocols, and endpoints <del> to use, and Candidate Racing, in which the necessary protocol handshakes are conducted so that the transport system can select which set to use.  This document structures candidates for racing as a tree. </del>  The most simple example of this process might involve identifying the single IP address to which the implementation wishes to connect,

Reviewer comments:
Oh yes, and it IS editorial ! :-D
Is "racing" really the right term? It might be a term of art that applies even in cases like this, but many of the relationships between different branches in the tree are based on preference rather than lowest latency. I don't feel strongly about this, but I don't know if this has been brought up yet, so I figured I'd mention it.
I agree that it may seem a bit misleading, but I think it's ok - it's just the word we use for it, and the term and how we use it is quite clearly defined in the Architecture draft, section 4.2.2. Just my 2c
I like "racing" - it's just a term....
Racing is defined in the architecture document; add a reference back there.
Thanks for fixing this!

Revised text:
Connection establishment is divided into two top-level steps: Candidate Gathering, to identify the paths, protocols, and endpoints  <ins> to use, and Candidate Racing (see Section 4.2.2 of I-D.ietf-taps- arch), in which the necessary protocol handshakes are conducted so that the transport system can select which set to use.  This document structures candidates for racing as a tree. </ins> The most simple example of this process might involve identifying the single IP address to which the implementation wishes to connect,
Original text:
The application should be notified whenever a Message or partial Message has been consumed by the Protocol Stack, or has failed to <del> send.  The meaning of the Message being consumed by the stack may vary depending on the protocol.  For a basic datagram protocol like UDP, this may correspond to the time when the packet is sent into the interface driver.  For a protocol that buffers data in queues, like TCP, this may correspond to when the data has entered the send buffer. </del>  5.1.3.

Reviewer comments:
I stared at this sentence for a while before I thought I'd made sense of it. PR forthcoming but I think this might need a little discussion.
lgtm

Revised text:
The application should be notified whenever a Message or partial Message has been consumed by the Protocol Stack, or has failed to  <ins> send.  The time at which a Message is considered to have been consumed by the Protocol Stack may vary depending on the protocol. For example, for a basic datagram protocol like UDP, this may correspond to the time when the packet is sent into the interface driver.  For a protocol that buffers data in queues, like TCP, this may correspond to when the data has entered the send buffer.  The time at which a message has failed to send is after the Protocol Stack or the Transport Services implementation itself has not successfully sent the entire Message content or partial Message content on any open candidate connection; this may depend on protocol-specific timeouts. </ins> 5.1.3.
Original text:
Calling Clone on a Connection yields a group of Connections: the parent Connection on which Clone was called, and a resulting cloned <del> Connection.  The connections within a group are "entangled" with each other, and become part of a Connection Group.  Calling Clone on any of these Connections adds another Connection to the Connection Group, and so on.  "Entangled" Connections share all Connection Properties except "Connection Priority" (see conn-priority) .  Like all other Properties, Connection Priority is copied to the new Connection when calling Clone(), but it is not entangled: Changing Connection Priority on one Connection does not change it on the other Connections in the same Connection Group. </del>  The stack of Message Framers associated with a Connection are also copied to the cloned Connection when calling Clone.  In other words,

Reviewer comments:
Clarify that the Connection returned by Clone will send a Ready Event or an InitiateError Event.
Clone() is analogous to Initiate(), so why doesn't it return ready events like initiate()?
This should be OK because Initiate doesn't generate the Ready event, etc, but the Connection does. Both Initiate and Clone return a Connection. We can try to clarify this.

Revised text:
Calling Clone on a Connection yields a group of Connections: the parent Connection on which Clone was called, and a resulting cloned  <ins> Connection.  The new Connection is actively openend, and it will send a Ready Event or an EstablishmentError Event.  The Connections within a group are "entangled" with each other, and become part of a Connection Group.  Calling Clone on any of these Connections adds another Connection to the Connection Group, and so on.  "Entangled" Connections share all Connection Properties except "Connection Priority" (see conn-priority) .  Like all other Properties, Connection Priority is copied to the new Connection when calling Clone(), but it is not entangled: Changing Connection Priority on one Connection does not change it on the other Connections in the same Connection Group. </ins> The stack of Message Framers associated with a Connection are also copied to the cloned Connection when calling Clone.  In other words,
Original text:
enabling applications written to a single API to make use of transport protocols in terms of the features they provide; <del> Unified interface to datagram and connection-oriented transports, allowing use of a common API for connection-establishment and closing; </del>  Message-orientation, as opposed to stream-orientation, using application-assisted framing and deframing where the underlying

Reviewer comments:
Suggested sentence to unambiguously explain datagram v. connection opening.
For me at least, it would be nice for the implementation draft to also initially remind readers that the Connection objects are relevant to all transports, including those that are not themselves connection-oriented.
Thought to be fixed in
Fixed in
Looks good! Thank you!

Revised text:
enabling applications written to a single API to make use of transport protocols in terms of the features they provide;  <ins> A unified interface to datagram and connection-oriented transports, allowing use of a common API for connection- establishment and closing; </ins> Message-orientation, as opposed to stream-orientation, using application-assisted framing and deframing where the underlying
Original text:
this property may be ignored. Safely Replayable: when this is true, this means that the Message <del> can be used by mechanisms that might transfer it multiple times - e.g., as a result of racing multiple transports or as part of TCP Fast Open.  Also, protocols that do not protect against duplicated messages, such as UDP, can only be used with Messages that are Safely Replayable. </del>  Final: when this is true, this means that the sender will not send any further messages.  The Connection need not be closed (in case

Reviewer comments:
Addition to clarify what happens when a transport system replays messages -
The current text says: If true, Safely Replayable specifies that a Message is safe to send to the Remote Endpoint more than once for a single Send Action. It marks the data as safe for certain 0-RTT establishment techniques, where retransmission of the 0-RTT data may cause the remote application to receive the Message multiple times. For protocols that do not protect against duplicated messages, e.g., UDP, all messages need to be marked as "Safely Replayable". To enable protocol selection to choose such a protocol, "Safely Replayable" needs to be added to the TransportProperties passed to the Preconnection. If such a protocol was chosen, disabling "Safely Replayable" on individual messages MUST result in a SendError. — I think this could perhaps be misleading, and suggest: 1. I would like to change /UDP/directly over UDP/ .... because clearly it is possible that a transport such as QUIC also uses UDP, but provides this sort of protection above the UDP layer. 2. This is still written from the perspective of the protocol. I think it is important here to also therefore add a sentence then clarifies that the application might be able to designed to detect and ignore such duplication. ‘Protection from replay of messages could be provided by an application when a transport system replays messages’.

Revised text:
this property may be ignored. Safely Replayable: when this is true, this means that the Message  <ins> can be used by a transport mechanism that might transfer it multiple times - e.g., as a result of racing multiple transports or as part of TCP Fast Open.  Also, protocols that do not protect against duplicated messages, such as UDP (when used directly, without a protocol layered atop), can only be used with Messages that are Safely Replayable.  When a transport system is permitted to replay messages, replay protection could be provided by the application. </ins> Final: when this is true, this means that the sender will not send any further messages.  The Connection need not be closed (in case
Original text:
100 <del> This property represents a hierarchy of priorities.  It can specify the priority of a Message, relative to other Messages sent over the same Connection. </del>  A Message with Priority 0 will yield to a Message with Priority 1, which will yield to a Message with Priority 2, and so on.  Priorities

Reviewer comments:
The text reads quire off when it says a priority property represents a hierarchy of priorities: This property represents a hierarchy of priorities. Could this better be: ‘A priority property is organised within a hierarchy of priorities. ‘?
When reading "hierarchy", it's easy to think that there may be priority sub-groups within priority groups, or something of that nature. Yet, this is not the case, it's just a flat priority assignment. Hence, to me, mentioning "hierarchy" here is misleading altogether. Therefore, I think we'd be much better off removing this sentence, i.e. replacing: with
Seems to resolving the odd wording.

Revised text:
100  <ins> This property specifies the priority of a Message, relative to other Messages sent over the same Connection. </ins> A Message with Priority 0 will yield to a Message with Priority 1, which will yield to a Message with Priority 2, and so on.  Priorities
Original text:
Properties may be Generic, applying regardless of transport protocol, or Specific, applicable to a single implementation of a single transport protocol stack.  Generic Connection Properties are defined <del> in connection-props below.  Specific Protocol Properties are defined in a transport- and implementation-specific way, and MUST NOT be assumed to apply across different protocols.  Attempts to set Specific Protocol Properties on a protocol stack not containing that specific protocol are simply ignored, and do not raise an error; however, too much reliance by an application on Specific Protocol </del>  Properties can significantly reduce the flexibility of a transport services implementation.

Reviewer comments:
Section 6 says. "Attempts to set Specific Protocol Properties on a protocol stack not containing that specific protocol are simply ignored, and do not raise an error" Should this be normative? "Attempts to set Specific Protocol Properties on a protocol stack not containing that specific protocol MUST be ignored, and MUST NOT raise an error" I note that this a random sentence where spotted that normative language could be used. I don't look for these kind of occasion systematically...
I could see a case that the first requirement to ignore, I think this actually a requirement for predictable interop? (in which case we could motivate that?) I am much less sure of the second MUST, and think an error notification is not an interop issue?
The first MUST is definitely important for code portability, and so I think this is a good suggestion. I'm also less sure of the second MUST, but I think it's good to keep: yes, errors can be ignored by an application, but they can also lead to application code like: adjust QUIC properties if error: adjust TCP properties If an application absolutely must do this and must find out what's going on, it can, it's ok for a Transport Services system to make everything readable... but throwing errors in addition is yet another hint for a programmer to start developing code like this. We should discourage such code. That's why I'd keep the MUST NOT (as a counter-example, "SHOULD NOT" would mean that there would have to be a good reason for the designer of a Transport Services system to make an exception - what would such a reason be? "This particular function of this particular protocol is so important, I think here I should really throw an error after all?" - Nah...).

Revised text:
Properties may be Generic, applying regardless of transport protocol, or Specific, applicable to a single implementation of a single transport protocol stack.  Generic Connection Properties are defined  <ins> in connection-props below. Protocol Specific Properties are defined in a transport- and implementation-specific way, and MUST NOT apply across different protocols.  Too much reliance by an application on Protocol Specific </ins> Properties can significantly reduce the flexibility of a transport services implementation.
Original text:
Security decisions, especially pertaining to trust, are not static. Once configured, parameters may also be supplied during connection establishment.  These are best handled as client-provided callbacks. <del> Security handshake callbacks that may be invoked during connection establishment include: </del>  Trust verification callback: Invoked when a Remote Endpoint's trust must be validated before the handshake protocol can

Reviewer comments:
Closes issue
We have a “ Terminology and Notation” section, but we don’t define these terms: Clone: Calling Clone on a Connection yields a group of Connections: the parent Connection on which Clone was called, and a resulting cloned Connection. Entangled connection: if we do we need this term, we should define and explain what is different. Callback: can we have a one line definition that explains the different with respect to an event that an application can also asynchronously receive.
I can take care of the first two; regarding callbacks, I think there should also be at least one sentence somewhere explaining the need (why are Events not good enough for security?). I remember that this was clearly said, and I remember understanding it :) but by now, I have forgotten, and I can't find the rationale written anywhere.
As I looked at this now, I felt that such definitions would seem a bit out of place in the "Terminology and Notation" section; rather, if we need to define it globally, the concepts of Cloning and Entanglement should be defined where we also define what our Connections are, what Transport Properties are, etc. - and this is in -arch. Thoughts?
This isn't need for entangled with the way used in PR
I'm adding the arch label so people notice :-)
The one action remaining is defining "callback" within the scope of section 4.3.
Looks like this will be addressed.

Revised text:
Security decisions, especially pertaining to trust, are not static. Once configured, parameters may also be supplied during connection establishment.  These are best handled as client-provided callbacks.  <ins> Callbacks block the progress of the connection establishment, which distinguishes them from other Events in the transport system.  How callbacks and events are implemented is specific to each implementation.  Security handshake callbacks that may be invoked during connection establishment include: </ins> Trust verification callback: Invoked when a Remote Endpoint's trust must be validated before the handshake protocol can