Very good question. What you are highlighting is essentially how complicated this code is.

The algorithm does two passes in order to build relationships. Given an Entity (not task or step, which are special cases), it will traverse the hierarchy upwards and resolve any links and store these ids in a dictionary. So if we start at a shot with id 123, it will go up and resolve the corresponding sequence id and then project id.

Armed with these "seeds", it will then run create_folders and traverse down from the root level and create folders. In the case there is a "seed", it will constrain folder creation based on this, effectively tracing back along the same project > sequence > shot path that it took when it travelled up.

Establishing these 'seeds' are only relevant when there are connections between levels in the folder hierarchy, such as a shot linked to a sequence. For user sandboxes, there is no such connection, so a seed is not needed. 

Out of interest, i did go down this path initially (adding this feature was surprisingly tricky!) and if you add the logic at the extract-upwards level, it will always be executed so there is no saving (I think at least).

I very much agree that it is not obvious why it is okay not to have the user added in the filters at the point when `extract_shotgun_data_upwards` is executed, but I am thinking this may be a broader issue with the general design rather than this case. 

TLDR: Cannot wait to refactor this code :)