If you put  a few extra
 a few extra puts lines in that code, it becomes a little clearer:
progression = (ring (chord :a, 'minor'), (chord :f, 'major'))
live_loop :chords do
  tick(:foo) # to count the number of chords played 0 1 2 3
  puts "foo: #{look(:foo)}"
  if look(:foo) == 3 then
    puts "tick value : "+ look(:foo).to_s
    tick(:next)
    tick_reset(:foo)
  end
  puts "next: #{look(:next)}"
  play progression.look(:next)
  sleep 1
end
Which gives the following output in the Log panel:
{run: 75, time: 0.0, thread: :live_loop_chords}
 ββ "foo: 0"
 ββ "next: 0"
 ββ synth :beep, {note: [69.0, 72.0, 76.0]}
 
{run: 75, time: 1.0, thread: :live_loop_chords}
 ββ "foo: 1"
 ββ "next: 0"
 ββ synth :beep, {note: [69.0, 72.0, 76.0]}
 
{run: 75, time: 2.0, thread: :live_loop_chords}
 ββ "foo: 2"
 ββ "next: 0"
 ββ synth :beep, {note: [69.0, 72.0, 76.0]}
 
{run: 75, time: 3.0, thread: :live_loop_chords}
 ββ "foo: 3"
 ββ "tick value : 3"
 ββ "next: 0"
 ββ synth :beep, {note: [69.0, 72.0, 76.0]}
 
{run: 75, time: 4.0, thread: :live_loop_chords}
 ββ "foo: 0"
 ββ "next: 0"
 ββ synth :beep, {note: [69.0, 72.0, 76.0]}
 
{run: 75, time: 5.0, thread: :live_loop_chords}
 ββ "foo: 1"
 ββ "next: 0"
 ββ synth :beep, {note: [69.0, 72.0, 76.0]}
 
{run: 75, time: 6.0, thread: :live_loop_chords}
 ββ "foo: 2"
 ββ "next: 0"
 ββ synth :beep, {note: [69.0, 72.0, 76.0]}
 
{run: 75, time: 7.0, thread: :live_loop_chords}
 ββ "foo: 3"
 ββ "tick value : 3"
 ββ "next: 1"
 ββ synth :beep, {note: [65.0, 69.0, 72.0]}
Now, looking at that, youβll notice that yes, your code calls tick(:next) when look(:foo) == 3, but even then, the first time around, look(:next) still only equals 0. Meaning that it will still play A min.
Then, tick(:foo) continues to increment :foo up to 3 a second time, and once look(:foo) == 3 the second time around, look(:next) ends up as 1, and F Maj is played.
Hope that makes sense! 
Hereβs two examples of ways you could achieve what you want:
progression = (ring (chord :a, 'minor'), (chord :f, 'major'))
live_loop :chords do
  tick(:foo)
  tick(:next) if look(:foo) % 4 == 0
  play progression.look(:next)
  sleep 1
end
Or,
progression = (ring (chord :a, 'minor'), (chord :f, 'major'))
live_loop :chords do |i|
  tick(:next) if i % 4 == 0
  play progression.look(:next)
  sleep 1
  i += 1
end
(They are almost identical - the second increments a counter manually rather than using a second tick/look pair)