OK, so the code does exactly what it is supposed to.
In your archive.php
you do this:
while ( have_posts() ) : the_post();
get_template_part( 'loops/loop', 'archive' );
So for every post (both of them) you include loops/loop-archive.php
file. And inside that file you don’t display only the current post from global loop, but you make your own, custom loop. And this one again iterates through all posts (because you set pre_get_posts
to -1.
So your code, after some simplifications looks like this:
while ( have_posts() ) : the_post();
// the part from get_template_part( 'loops/loop', 'archive' );
$query = new WP_Query($args);
if ($query->have_posts()) :
while ($query->have_posts()) :
$query->the_post();
// display the post
So yes – it shows 4 posts instead of 2. And it will display 9 posts instead of 3, if there will be 3 posts – because for every post you display all posts.