Sorry, but you've got some fundamental misconceptions here.
First off - and this is going to sound pedantic, but it's important to get our terminology straight - a "callback" is any function that gets passed to another function so that it can be "called back to" later on. It is entirely possible for this to happen synchronously. Example:
function doACallback(theCallback) {
theCallback()
}
doACallback(() => console.log('hello'))
console.log('world')
This code runs synchronously; the event loop is not involved at all. It will print "hello" and then "world".
Now, the most common usage of callbacks is for various asynchronous things that happen on the event loop. Input events, setTimeout/setInterval, and yes, Promises.
However, async/await only concerns itself with Promises. Not with setTimeout or setInterval or events. So if you want to use it to take something asynchronous and make it appear/behave as if it were synchronous, that thing needs to be in the form of a Promise. You demonstrate this in your fiddle by wrapping setTimeout in a Promise inside the sleep() function.
But, you then go and use a setInterval, which is totally outside the domain of Promises, and so async/await has nothing to say about it. Your example only demonstrates that by "doing something async" you're putting the ordering of certain things at the mercy of the event loop. In practice, the answer to this "problem" is that if the ordering of asynchronous things matters to your logic, then that order needs to be enforced via .then() chaining or async/await or otherwise. Never just rely on the ordering of the event loop itself. If you do, then you already have a race condition, whether you've realized it or not. Both of the code samples would be problematic if you ever did this in production.
Further: this is most definitely not the same problem that C++ solves with semaphores, mutexes, etc. Both languages can have race conditions, but JavaScript cannot have data races, which is what those constructs exist to deal with. That is why JavaScript doesn't have them.
To get specific: in JavaScript, only one thread can actually be running (with the memory space these variables exist in) at a time. The async stuff may make this less than obvious, but it's a firm truth. JavaScript code can't be interrupted arbitrarily, it can only yield control of the thread at a given await. You might argue that making this invisible might make it easier for people to write those kinds of bugs without noticing, but it certainly wouldn't "completely break the language".