Coroutines (or the concept of saving context to come back to) is already heavily explored in robotics in recent years. Behaviour Trees [1] approximates what coroutines do in system level controlled ticks mainly to avoid pitfalls of state machines. They are also extensively used in game development too. ROS2 have Nav2[2] package which is based on BTCpp library [3]. Not surprisingly BTCpp library uses boost coroutines to implement some behaviours.
Shameless plug, I have also been developing (weren't planning to advertise yet so no docs or plans for release) a behaviour based C++ library completely built on coroutines [4] to avoid some problems of "Behaviour Tree"s.
Given your expertise, why use behaviour trees when coroutines are available? What value do they provide in languages like javascript where generators work well?
I'm writing a game that uses both behavior trees and coroutines (via C# generators), and I have found that they are not quite interchangeable.
The main thing is that the execution model is different. I think of the behavior tree as being evaluated from the root on every tick, whereas with coroutines, you are moving linearly through a sequence of steps, with interruptions. When you resume a coroutine, it picks up exactly where it left off. The program does not attempt to re-evaluate any preceding code in the coroutine in order to determine whether it's still the right thing to be executing. By contrast, a behavior tree will stop in the middle of a task if some logic higher up in the tree decides that you need to be on a different branch.
What we end up doing is composing behavior trees with coroutines as leaf nodes. It works quite nicely, although I wish there was a way to express the structure of the behavior tree in a more elegant way. We do the obvious thing: each node in the tree is some subclass of a Node base class, representing a logical operation like "if" or "do these in parallel".
I very much feel OP's angst about creating a pseudo-programming language-within-a-language by creating what are basically ad hoc AST nodes, but I haven't come up with a better solution. Maybe something like React, where you use basically imperative code to describe a structure, and there is some ambient state that gets properly reconciled by a runtime that you don't touch directly.
Behaviour Trees are a bit more than that. They also effect/advice how you structure your project (not component based but behaviour based: exp. you don't have "controller" component in your architecture to handle all locomation but "go_to_pose" or "turn_around" behaviour) plus there are tooling provided around those architectures.
Design of Behaviour Trees were not an answer to lack of coroutines/generators (although they were missing from C++ standards until C++20) but an alternative to state machines.
Although I agree that "tick" based BT implementation is outdated and should completely be replaced by coroutines and mandatory yields (thats what I did in my implementation). There is still value in behaviour based architectures in robotics. They make building complex/reactive behaviours much easier than component based ones.
Also a super analogy to show new programmers how complexity increases if you introduce unnecessary dependencies.