My comment is based on the fact that the odds of finding a safe way to guarantee this would not be practical for several reasons:
- the changes required to fix this just might break something else ... or (worse yet) existing applications that (perhaps unwittingly) rely on the current behavior.
- there are probably 3 different Metacello repositories actively used at the moment and if I DID fix this behavior the odds are that you'd have to ask the Pharo maintainers to implement their own fix (or port the fix from my repo) in their fork(?) of Metacello. The Pharo version of Metacello has been independent of the "master" Metacello repository for at least 5 years or more ...
I did read the code a bit ... and the preload and postload doits are currently tied to the load directive structure and are subject to the whims of the linear and atomic load rules.
If it wasn't for Seaside, which to this day requires linear load in order to initialize itself correctly, I would have made the detault rule #atomic instead of #linear, but changing the default rule 10 years after the fact would likely wreak havoc :)
Anyway, I would expect that using atomic loads, the postload and preload doits would be evaluated once ... with linear loads ... I don't think it would be possible/correct to skip the doits which are literally supposed to be evaluated before a package is loaded or after it is loaded ... and if it is being executed multiple times, I don't think we can tell that the package is going to be loaded multiple times (any easier than you can ... in fact with linear load directives I'm not even sure we've even read the baselines that would follow ... we read/load one chunk at at time ... but this is conjecture at this point in time ... as I said earlier, I would have to look at the Transcript output to even begin to try to understand what might be going on.
It's worth taking a crack at arranging for atomic loads, since might actually get the behavior that you want...