Hello Marc!
(haven't read about you for a long time)
I believe the semantics in nix has been like this all the time - the "@ pattern" is binding exactly the set that was *passed*.
I think it's perhaps a simpler way than what people would expect intuitively in the most common use cases. I had been caught by this a long time ago as well, and there's surely a discussion thread about it somewhere (I can't find it fast). The { foo, bar ? baz } "pattern" doesn't really change what was passed - it just provides bindings to parts of that, with defaults to parts that were missing - at least these are *my* ways to remember since I've found this "issue" long ago, and this semantics actually have become to make much sense to me over time.
I'm not sure if I'm being helpful here. Anyway, I find this semantics unlikely to change easily, as it would be an incompatible change (though arguably not likely to break many use cases).
--Vladimir