The problem is that when you build at this layer, you end up writing far more scheduling code than business logic. Eventually you've built the abstractions we already use today.
The vast, vast majority of software, and software developers, simply do not care about core affinity, NUMA, noisy neighbors, etc.
Even on systems or situations where this matters (massive number of cores and memory, multiple sockets, thousands of threads, etc.) the juice is rarely worth the squeeze.
Doubly so when you end up being I/O bound anyways.
Nearly every software developers wants their software to work across multiple deployment targets. Maybe you just target x86-64, and you don't care about the number of CPUs because you'll be upgrading your servers every couple of years.
No one wants to deal with difficult-to-reproduce issues related to scheduling in niche configurations. It's much more efficient for runtime or compiler engineers to solve these problems for us, leveraging the vast amount of resources of corporations to develop and test these features. Then you have a place your code can live happily ignorant of its runtime constraints.
And that, my friend, is the beauty of our industry.
... until you end up writing code that runs on ARM, which has weak memory ordering.