Hi everyone,
**1. Is it worth standardizing?** Does this belong in the standard, or can it live as a library? The central claim is that a small normative protocol unlocks a large amount of interoperable user code (the "What We Get" table in Section 2). Is that interoperability argument convincing? Is the benefit worth the committee time and the standard surface it would consume?
I believe it is. The main reasons C++20 coroutines never got the adoption they deserved is that coroutine types don't interoperate across ecosystems, Boost.Asio being the obvious example. There have been attempts to address this, std::task<T> for instance, but standardizing a coroutine type just relocates the interoperability problem instead of removing it: anyone not using that type is still locked out, and the ecosystems that matter for I/O won't abandon their own types to adopt it. So I think this is heading in the right direction. The common language between C++20 coroutine types should be a protocol, not a single standardized type.
**2. Did the use of AI affect your perception?** This paper, and the review program you are reading this on, were developed with heavy AI assistance, and I am not hiding that. I want to know candidly whether knowing or suspecting that changed how you read it. Did it raise or lower your trust? Did you go looking for tells, and did you find any? Did it make you more or less rigorous than you would be with a paper written entirely by hand? I would rather you name this in your review than leave it unsaid. The answers matter as much to me as the technical feedback, and they will shape how the Network Endeavor and this program handle AI-assisted work.
In my view, using AI assistance to help with wording is perfectly reasonable. However, writing a standards paper requires such a high level of scrutiny and domain expertise that the effort spent on the technical content, analysis, and review typically far outweighs the effort spent on the writing itself.
**3. What is the technical quality?** Are the concepts sound and precisely stated? Do the central claims hold up - zero per-operation allocation under type erasure, symmetric-transfer resumption, automatic frame-allocator propagation, and the structured-concurrency argument in Section 5? Is the implementation evidence (Capy, Corosio, the benchmark table, the Compiler Explorer demo) credible and reproducible? Where is the reasoning weakest?
I'm not sure if std::stop_token is the best fit for cancellation in a coroutine library, and the main reason is that it is designed around the assumption that cancellation is relatively rare. In that sense, it's somewhat analogous to the distinction between exceptions and std::error_code/std::expected. std::stop_token is structured more like an exception mechanism: cancellation is relatively expensive to trigger, with the design optimized for the case where stopping is exceptional. In racing compositions, however, cancellation is often the expected outcome of normal execution. For example: auto [ec, r] = co_await wait_any(socket.connect(ep1), socket.connect(ep2)); On every successful completion, one of the connect operations is cancelled. Since this is part of the normal control flow, it seems desirable for the associated costs to be minimal and predictable, rather than optimized around the assumption that cancellation is uncommon. Because of that, I don't think std::stop_token is an ideal choice here: 1. Thread safety is unconditional. Although it is implemented using atomics, those typically compile to lock-prefixed RMW instructions (lock xadd, lock cmpxchg) that acquire exclusive ownership of the cache line and act as full memory fences. As a result, even a single-threaded or strand-based executor pays for synchronization guarantees it never actually needs. 2. std::stop_source requires a heap-allocated control block created via a regular new. By contrast, a coroutine frame already provides stable storage that could hold cancellation state inline, avoiding the allocation entirely.
**4. What is missing?** What would you need to see before LEWG could act on this? I am looking for gaps in specification or wording, unaddressed edge cases, missing comparisons (against existing coroutine task libraries, or other parts of `std::execution`), lifetime or cancellation corners, threading hazards, and anything the paper moves past too quickly. Tell me what you went looking for and did not find.
The IO prefix in the concept names seems unnecessarily restrictive. The model appears applicable to non-I/O tasks as well, so a more general name might better reflect its intended scope. Regards, Mohammad