Root cause: expires_at == today was NOT filtered (used '< today'), so a product expiring ON today kept its resources in desired scopes -> no diff -> no removal. Changed to '<='. Applied to W3 (CP + grant loops) and W2 (active filter). Also W2 previously had NO expiry filter on active CPs at all.