Because the "$id" :"#bar" (a plain-name fragment declaration) is only resolved against its immediate base, which is "$id": "other.json", producing "other.json#bar". It does not "see" the earlier bases.
The JSON Pointer fragments are calculated differently, as they specifically state 'When an "$id" sets the base URI, the object containing that "$id" and all of its subschemas can be identified by using a JSON Pointer fragment starting from that location. This is true even of subschemas that further change the base URI.' (note second sentence).
It's debatable as to how ideal this is, but as the current editors/authors inhereting an existing spec, this seemed to be the behavior that most people expected.
-henry