While the callback can filter log messages to the desired level, setting the log level in libloot means that it can avoid doing work to construct error messages that may then be discarded.
When a vertex is unfinishable during a groups graph DFS, that means all the plugins in the path leading up to it are also unfinishable, and the comment I'd written in the code acknowledged that but the impl didn't.
The old approach made sense once, when the load order was the current load order and not the order that the plugins are given in, but that was a long time ago.
The mutex in the game cache wasn't very effective, instead move the
mutex out to the only place that concurrently writes to the cache.
This does mean that there isn't protection against calling
GameInterface::LoadPlugins() concurrently from multiple threads, but
no effort has been made to make libloot's public API thread-safe anyway.