def flatten_diff(diff):
    """
    For spawning, a 'detailed' diff is not necessary, rather we just want instructions on how to
    handle each root key.

    Args:
        diff (dict): Diff produced by `prototype_diff` and
            possibly modified by the user. Note that also a pre-flattened diff will come out
            unchanged by this function.

    Returns:
        flattened_diff (dict): A flat structure detailing how to operate on each
            root component of the prototype.

    Notes:
        The flattened diff has the following possible instructions:
            UPDATE, REPLACE, REMOVE
        Many of the detailed diff's values can hold nested structures with their own
        individual instructions. A detailed diff can have the following instructions:
            REMOVE, ADD, UPDATE, KEEP
        Here's how they are translated:
            - All REMOVE -> REMOVE
            - All ADD|UPDATE -> UPDATE
            - All KEEP -> KEEP
            - Mix KEEP, UPDATE, ADD -> UPDATE
            - Mix REMOVE, KEEP, UPDATE, ADD -> REPLACE
    """

    valid_instructions = ("KEEP", "REMOVE", "ADD", "UPDATE")

    def _get_all_nested_diff_instructions(diffpart):
        "Started for each root key, returns all instructions nested under it"
        out = []
        typ = type(diffpart)
        if typ == tuple and len(diffpart) == 3 and diffpart[2] in valid_instructions:
            out = [diffpart[2]]
        elif typ == dict:
            # all other are dicts
            for val in diffpart.values():
                out.extend(_get_all_nested_diff_instructions(val))
        else:
            raise RuntimeError(
                "Diff contains non-dicts that are not on the "
                "form (old, new, inst): {}".format(diffpart)
            )
        return out

    flat_diff = {}

    # flatten diff based on rules
    for rootkey, diffpart in diff.items():
        insts = _get_all_nested_diff_instructions(diffpart)
        if all(inst == "KEEP" for inst in insts):
            rootinst = "KEEP"
        elif all(inst in ("ADD", "UPDATE") for inst in insts):
            rootinst = "UPDATE"
        elif all(inst == "REMOVE" for inst in insts):
            rootinst = "REMOVE"
        elif "REMOVE" in insts:
            rootinst = "REPLACE"
        else:
            rootinst = "UPDATE"

        flat_diff[rootkey] = rootinst

    return flat_diff