As you observe in your comment, in the first variant there is no relation between Items and the goal append(_, [X,Y|_], Left), so on backtracking this goal will enumerate all its infinitely many solutions.
Your second approach is the best one for this problem, but indeed in general you sometimes need to restrict the search space in other ways.
The problem with the first clause is that Left is completely unconstrained. But we know that we never want it to be longer than Items. So we can write a predicate to express "Items is a list, and Left is a shorter or equal length list":
list_shorterorequal(_List, []).
list_shorterorequal([_|List], [_|ShorterOrEqual]) :-
list_shorterorequal(List, ShorterOrEqual).
?- list_shorterorequal([a, b, c], ShorterOrEqual).
ShorterOrEqual = [] ;
ShorterOrEqual = [_G938] ;
ShorterOrEqual = [_G938, _G941] ;
ShorterOrEqual = [_G938, _G941, _G944].
And then you can adapt your first implementation like this:
repeat_pair_1x(Items) :-
list_shorterorequal(Items, Left),
append(_,[X,Y|_],Left),
append(Left,[X,Y|_],Items).
And this succeeds once, then terminates quickly:
?- repeat_pair_1x([1,2,3,4,2,3,5]).
true ;
false.
If your Prolog has a between/3 predicate (they usually do), you could also use that to restrict the length of Left before we know anything else about Left itself:
repeat_pair_2x(Items) :-
length(Items, ItemsLength),
between(2, ItemsLength, LeftLength),
length(Left, LeftLength),
append(_,[X,Y|_],Left),
append(Left,[X,Y|_],Items).
This also terminates nicely:
?- repeat_pair_2x([1,2,3,4,2,3,5]).
true ;
false.
Note that these two predicates behave slightly differently on the most general query, and in general if the argument of the call is not bound to a finite list:
?- repeat_pair_1x(Items).
Items = [_G918, _G924, _G918, _G924|_G940] ;
Items = [_G918, _G924, _G930, _G918, _G924|_G946] ;
Items = [_G918, _G924, _G930, _G924, _G930|_G949] ;
Items = [_G918, _G924, _G930, _G936, _G918, _G924|_G952] ;
Items = [_G918, _G924, _G930, _G936, _G924, _G930|_G955] .
?- repeat_pair_2x(Items).
Items = [_G918, _G921, _G918, _G921] ;
Items = [_G918, _G921, _G918, _G921, _G930] ;
Items = [_G918, _G921, _G924, _G918, _G921] ;
Items = [_G918, _G921, _G924, _G921, _G924] ;
Items = [_G918, _G921, _G918, _G921, _G930, _G933] .
By calling length/2 on Items in the second variant, we force it to be a finite list. There might be cases where you don't want this.