It’s been a while, but IIRC Luigi uses a highly-stateful notion of “targets” to determine whether a task finished successfully. These targets conflate data outputs and state outputs, meaning you can’t adjust the state of a task without modifying the data it produced. Conversely, Airflow only supports state outputs. Prefect supports both state and data outputs independently.