That's a great way of thinking about async structure - and perhaps surprisingly (since switching from asyncio or trying fledgling implementations as part of my day job is a no-go ;) immediately useful. A large part of what I do is wrap existing libraries so they can be used with asyncio- the idea being that once wrapped correctly it becomes easy to throw together applications quickly and correctly. For example 'cassandra' or the python gRPC libraries. These both offer async-ish style APIs, smattered with some callback style stuff and a handful of functions that block but probably shouldn't. There are no standard examples of 'best practice' in how to do this - the asyncio docs focus on using existing asyncio components. As a result I end up with stuff that works until I need to worry about error handling, cancellation, restarting components and then I cry my heart out in the mailing lists and generally make a mess.
My key takeaway after skimming your blogs is that implementations should 'respect causality'. Aim for
await my_implementation() to not spawn any anonymous tasks that can't be controlled, to only complete when it really has finished everything it started under the hood, and to correctly respect cancellation. Limit APIs to coroutines only (ie limit yourself to a 'curio' style) to make things simpler to reason about. If you must spawn tasks, keep them in logical groups - eg within a single function (or nursery if you have such an implementation) and make sure they are all finished before the function ends.