I know that var/1, nonvar/1 and !/0 are impure primitives, but does their use make every program that uses them impure?
Regarding the question "is the above plus/3 really pure?" I can only say: I have no idea which properties are preserved here, because the code, due to all these extra-logical predicates, is so complicated and hard to follow that it is hard to tell what it is actually doing. And I really must say doing in this case, because this is far from declarative code that is describing something we can comparatively easily talk about. All kinds of properties we expect from declarative code may be destroyed in this case.
The best way to generally prove that a relation is pure is to restrict yourself to the pure and monotonic subset of Prolog. It is for this reason that this property is so important, because this subset is closed under composition. Once you leave this subset, it quickly gets really hard to prove any properties whatsoever about your programs, as your example nicely demonstrates.
For example, to prove your plus/3 monotonic, you need to show, among many other things, that if ?- plus(X, _, _), X = T fails for any term T, then ?- X = T, plus(X, _, _) does not succeed. Since it is in general not decidable whether a query fails, loops or succeeds and we therefore in general cannot even determine a single side of this implication, let alone both, I can only say: Good luck with that!