do_action Nested List

If you want to return a value in your hook, use apply_filters instead of do_action, like:

$project_option .= '<ul class="project-list">';
    foreach( $projects as $project ) {
    $project_id = $project->ID;
    $project_option .= '
        <li class="project" id="project-' . $project_id . '">
            <span class="project-title">' . get_the_title( $project_id ) . ' </span>
            <span class="project-status-title">' . __( 'Project Status: ', 'client-area' ) . '</span>
            <span class="project-status">' .  get_post_meta( $project_id, 'project-status', true ) . '</span>' .
            apply_filters( 'my-task-action', $project_id ) . '
        </li>';
    }
$project_option .= '</ul>';
echo $project_option;

and then have an add_filter like

add_filter('my-task-action', 'wpse241018_getTaskActions');

function wpse241018_getTaskActions($project_id){ 
    $task_option .= '<ul class="task-list">';
    foreach( $tasks as $task ) {
        $task_id = $task->ID;
        $task_option .= '
        <li class="task project-' . $project_id . '" id="task-' . $task_id . '">
            <span class="task-title">' . get_the_title( $task_id ) . ' </span>
            <span class="task-status-title">' . __( 'Task Status: ', 'client-area' ) . '</span>
            <span class="task-status">' .  get_post_meta( $task_id, 'task-status', true ) . '</span>
        </li>';
     }
    $task_option .= '</ul>';
    }
    return $task_option; 
}