async def project_activate(existing_project_path: str, file_names: Optional[List[str]] = None, **kwargs) -> Dict[str, Union[str, List[str], str]]:
    """
        Activates an existing project, granting permission to operate within its directory.
        Returns project file structure and/or content of specified files. Updates the AppState
        with the activated project and its tree structure.

        Args:
            existing_project_path (str): The path to the existing project directory.
            file_names (List[str], optional): A list of file names within the project to read and return their content.
            **kwargs: Additional keyword arguments.
                - return_structure (bool, optional): If True, returns the full project structure. Defaults to False.

        Returns:
            Dict[str, Union[str, List[str], str]]: A dictionary containing:
                - 'status': 'activated' if successful, 'error' if an issue occurred.
                - 'message': Additional information, especially useful for error descriptions.
                - 'project_name': The name of the activated project.
                - 'project_structure': List of all files in the project as relative paths (if return_structure is True).
                - 'file_contents': Dict of file contents with relative paths as keys (if file_names provided).

        Note:
            This function updates the AppState with the activated project path and its tree structure.
    """
    try:
        return_structure = kwargs.get('return_structure', False)
        # Validate the project path
        if not os.path.isdir(existing_project_path):
            return {
                "status": "error",
                "message": f"The specified path does not exist or is not a directory: {existing_project_path}"
            }
        # Get the absolute path
        project_path = os.path.abspath(existing_project_path)
        # Update app state with the activated project
        app_state = get_app_state()
        app_state.active_project = project_path

        result = {
            "status": "activated",
            "project_name": os.path.basename(project_path)
        }

        if file_names:
            # Read contents of specified files
            file_contents = {}
            for file_name in file_names:
                full_path = os.path.join(project_path, file_name)
                if os.path.isfile(full_path):
                    with open(full_path, 'r') as f:
                        content = f.read()
                    file_contents[file_name] = content
                    # Update file context
                    file_context = get_file_context()
                    file_context.add_or_update_file(file_name, content, "read")
                else:
                    logging.warning(f"File not found: {file_name}")
            result["file_contents"] = file_contents

        if return_structure:
            # Get the file structure
            project_structure = await list_files_for_project(directory=project_path)
            result["project_structure"] = project_structure


        app_state.update_active_project_tree()
        return result

    except Exception as e:
        logging.error(f"Error in project_activate: {str(e)}")
        return {
            "status": "error",
            "message": str(e)
        }
    finally:
         # Log the activation attempt
        logging.info(f"Project activation {'successful' if 'status' not in locals() or locals()['status'] == 'activated' else 'failed'} for: {existing_project_path}")


```
async def list_files_for_project(directory: str = ".", ignore_patterns: List[str] = None) -> List[str]:
    """
        we need to make sure that we are not going so deep into directories with extreme length like code execution environment
        elegantly check the length of any given directory bin, lib etc

    """
    if ignore_patterns is None:
        ignore_patterns = ['.git', '__pycache__', '*.pyc']
    
    try:
        files = []
        for root, dirs, filenames in os.walk(directory):
            dirs[:] = [d for d in dirs if not any(fnmatch.fnmatch(d, pattern) for pattern in ignore_patterns)]
            
            for filename in filenames:
                if not any(fnmatch.fnmatch(filename, pattern) for pattern in ignore_patterns):
                    files.append(os.path.relpath(os.path.join(root, filename), directory))
        
        return files
    except Exception as e:
        logging.error(f"Error listing files: {str(e)}")
        return []
```

please analyze the two functions and read the docstrings to understand how they work together as well as my concerns with potential bugs i have found. Afterwords i will provide you with a full stream of reference to check against with any of your solutions or understanding.