You have a zero-length match there, and you have a capturing group. When the regular expression for re.findall has a capturing group, the resulting list will be what's been captured in those capturing groups (if anything).
Four positions are matched by your regex: the start of the string, before the first b, before the second b, and before the third b. Here's a diagram, where | represents the position matched (spaces added for illustration):
 b b b b
|         captures the next b, passes
 b b b b
  |       captures the next b, passes
 b b b b
    |     captures the next b, passes
 b b b b
      |   captures the next b, passes
 b b b b
        | lookahead fails, match fails
If you didn't want a capturing group and only want to match the zero-length positions instead, use (?: instead of ( for a non-capturing group:
(?=(?:b))
(though the resulting list will be composed of empty strings and won't be very useful)