Do not track nodes without incoming edges in TaskDependencyGraph and use added tasks as entry points to execution plan in DefaultTaskExecutionPlan
Simplify adding graph nodes and edges
Differentiate between soft and hard edges in TaskDependencyGraph
Add mustRunAfter dependencies before regular dependencies to execution plan, continue execution of task with must run after dependency if the dependee task fails
Reduce number of task lookups in graph
Merged TaskInfo and TaskDependencyGraphNode
Determine executionPlan only after all tasks are added
Lazy evaluation of must run after dependencies