For dup check you put the join inside the repeat with a once like this.
once(join(", ", ${Species}))
Then add a constraint that checks against this list like (the comma is to avoid matches like PACE and PACE5 for example.
${Species}='' or not(contains(${AllPlantsCheck}+",",${Species}+","))
Note in the latest versions of 123 there is a slight bug where the first repeat acts differently than the rest. To fix that I added a TempCount field in the repeat with a calc of once(count(${SomeOtherRepeatField}))
then change the constraint to
if(${TempCount}=0, 1,${Species}='' or not(contains(${AllPlantsCheck}+",",${Species}+",")))
You will see how the first one is a bit off.
For the summary page I just use join with \n and a grid appearance and since the repeats are always in order it just all lines up for you like magic.
Other way to do summaries is inside your repeat add a calc of concat(Field1, " ", Field2, " ", etc) then on your summary page do a join \n with that concat field.
Hope that makes sense.