Ok, there's a bit of confusion what should happen and this is unfortunate. The idea of the constructor is: these are the elements to build the bucket with. This means that the predicate expression passed in is actually the predicate expression of the bucket. It's not wrapped again.
So calling 'Add' after that, will add to that predicate expression object.
In the case of the 2nd example, you start with an empty predicate expression, and you add the predicate expression with the 3 or-ed predicates to that. After that calling add again, adds to the original one, the empty predicate expression you started with.
It's a line in the reference manual documentation on the constructor:
Filter to use. Will be set as the initial PredicateExpression contents
this is a bit misleading, as it is up for interpretation and can cause confusion like we've seen in this thread.
My initial reaction was as well: they should be the same, but the API is a little bit different. We can't change the API however, so no fix for this to make them align can be issued. This might sound a little odd, but wrapping it in a predicate expression causes a different sql string which might cause tests to fail for no reason. It also might cause code to fail which uses this feature and assumes the predicateexpression is the same object (as the api intended). We'll update the comment on the constructor to make it more clear that a passed in predicateexpression will be used as the predicateexpression of the bucket.
Hopefully this clears things up a bit