At first I wasn't sure I liked having there be two different functions for sync vs. async, but I've come around to liking this approach.  For one thing, whenever we get around to introducing real time linting as you type, this gives us a nice migration path -- we can automatically opt in all legacy sync linters, while leaving async linters to opt in manually only if they feel like they're generally fast enough.