As has been pointed out, given the nature of your data it is possible that you will get combinations of entries that cannot hold to your rule. It is also not a simple task to sort based on your requirements as each node needs to know the data in other nodes to make a decision.
That being said, I have given it a crack. While not simple, I have likely overthought the process. It also is not an elegant solution, and definitely will not be an efficient process. I imagine it will take quite a while to execute on large data sets.
I have tested it with your sample data, and it seemed to work out just fine. I added in some extra data, including data that cannot hold to your requirements, and I feel the resultant order would suffice given the circumstances. It would be simple to change it to exit and/or result in an error instead if it can't be sorted properly. Assuming that there will always be a correct order, this should work. Definitely requires more testing:
class Node:
    """
    A node representing the inner dictionary of files. Keeps rack of
    lesser and greater nodes so that they can be placed into a list in appropriate order.
    """
    def __init__(self, file_dict: dict):
        self.file_dict = file_dict
        self.files = {i[0]: i[1] for i in file_dict['files']}
        self.greater_nodes = []
        self.lesser_nodes = []
        self.on_stack = False
        self.in_list = False
    def compare_nodes(self, other_node, file_name):
        """Compares the nodes to each other and lists each other in either their greater or lesser groups"""
        if self.files[file_name] < other_node.files[file_name]:
            self.lesser_nodes.append(other_node)
            other_node.greater_nodes.append(self)
        else:
            self.greater_nodes.append(other_node)
            other_node.lesser_nodes.append(self)
    def place_node(self, node_list, lesser_list):
        """Places node in given list, but first checks for any greater node in the list and places those first"""
        self.on_stack = True  # If on stack and referenced as greater, place into list.
        lesser_list += self.lesser_nodes
        for node in self.greater_nodes:
            if node not in lesser_list:  # Don't go to nodes that are in any way lower than those on the stack.
                if node.on_stack and not node.in_list:
                    node_list.append(node.file_dict)
                    node.in_list = True
                    node.on_stack = False
                elif not node.in_list:
                    node.place_node(node_list, lesser_list)
        if not self.in_list:
            node_list.append(self.file_dict)
            self.in_list = True
        self.on_stack = False
    def __repr__(self):
        return f'{self.file_dict["#"]}'
class FileObj:
    """
    Representation for each different file name.
    Tracks nodes with common file name so that they can be appropriately compared.
    """
    def __init__(self, name: str):
        self.name = name
        self.nodes = []
    def add_node(self, new_node: Node):
        """Add another node to the list for the file object, making sure to
        compare any new nodes to old based on file name."""
        for old_node in self.nodes:
            new_node.compare_nodes(old_node, self.name)
        self.nodes.append(new_node)
    def place_nodes(self, node_list):
        """Place all nodes into a given list."""
        # Sorts nodes first (shouldn't be necessary in most cases, as they should all have valid relational data).
        self.nodes.sort(key=lambda x: x.files[self.name])
        for node in self.nodes:
            if not node.in_list:
                node.place_node(node_list, [])
    def __repr__(self):
        return f"{self.name} : {self.nodes}"
def sort_function(unsorted_list):
    # Get dict of file objects.
    file_dict = {str(y[0]): FileObj(y[0]) for x in unsorted_list for y in x['files']}
    file_order = sorted([x for x in file_dict.keys()])  # Reference of file names in sorted order.
    # Get list of dicts from the unsorted list as node-objects.
    node_list = [Node(x) for x in unsorted_list]
    # Get nodes to assign themselves to file_objects
    for node in node_list:
        for file in node.files.keys():
            file_dict[file].add_node(node)
    # Go through file_order to start placing nodes in lexicographical order.
    final_list = []
    for file_name in file_order:
        file_obj = file_dict[file_name]
        file_obj.place_nodes(final_list)
    # Print results to check.
    print(final_list, "\n")
    for d in final_list:
        print(d)
def main():
    unsorted_list = [{"#": "1", "files": [("test.txt", 1), ("example.out", 1)]},
                     {"#": "2", "files": [("other.txt", 0), ("test.txt", 3)]},
                     {"#": "3", "files": [("example.out", 0)]},
                     {"#": "4", "files": [("test.txt", 2)]}]
    sort_function(unsorted_list)
if __name__ == '__main__':
    main()