It doesn’t (strictly speaking). Your initial use_module/1 goal makes f/1 available in user. As all modules inherit by default from user, the foo2:f(Z) goal succeeds by looking up f/1 in user.
Note that this doesn’t create a module foo1. In fact, it creates a predicate :-/1 with a single fact. It may comes as a surprise, but :-/1 is not a predicate, so you can define it. Just assert(foo1:f(1)) creates a module foo1 with a predicate f/1. Next you can use export/1 and import/1 to import and export stuff from your module (or simply directly call in there).
Right! I discovered that since I posted. It looked like way because I was replicating what I was trying via the foreign language interface – trying to issue a directive through the API’s query/assert calls. This got left in because I thought I’d succeed somehow (it succeeded, but as an assert not as a directive). Noob mistake.