Status update on the filtering: I have a new search algorithm which appears to be giving correct mirror results, and is also (possibly much) faster.
Technical details you can ignore if you want but I’ll write out in case some of you are interested (and it helps me to describe it in words):
Filtering with hierarchy has three states: negated, matched, not matched. If a parent is negated it negates the whole child tree. If a parent does not match but a child in its tree does, then the parent actually does match. So whether or not each item matches is very dependent on the tree around it.
The old algorithm (originally written in 2014) looped through each item, then their children, and then if a child matched it propagated back up the tree to all parents. That worked fine, but then mirroring confused the whole thing because a child of a mirrored item has a different path to the root than the mirrors. There was lots of propagating match state up to parents and across mirrors and linked items and their parents, which never quite worked right. For example if a child of a mirrored item matched, it wasn’t propagating correctly through all mirror items. It also got a bit slow because it had to visit each item more than once.
The new algorithm calculates its own match state (or if it’s a mirror calculates the mirrored item’s match state instead), then passes that down to its child tree, then combines its own state with its children, and passes its state back up the tree. This seems to be working much more correctly, and only hits each item once which may make it much faster.
In my test document it looks like it’s matching the previous behavior and fixing the bad behavior with mirrors. I’m going to keep playing with it and write a bunch of tests to make sure it’s returning correct results for every case I can think of. Then I’ll release an update which uses the new algorithm only if you have “Test beta features” enabled, so if you find any bugs you can go back to the old one while I fix it.