Now it's obvious. YAST and migrations scripts explicitly select the products in addition to dup, that's why it works for them (they'd select "openSUSE Leap 15.2" before the solver run). On a plain zypper dup however "openSUSE Leap 15.2" is not yet selected. We'd need 2 passes (one to compute the product fates and a 2nd one after adding the weakremovers)....