I restored dataframe_step and deleted DataFramePhase. A dataframe_step can be used in a reshape phase, or in a regular phase if it doesn't happen to reshape the data.
ReshapePhase can now take a list of steps just like Phase, so that is now common logic between them.
What this sets us up for:
More work on row numbers as we discussed - will go into the regular Phase and not ReshapePhase. ReshapePhase will always create a new generation of row numbers.
I'm thinking it would be useful for steps to make more robust promises about what they're supposed to do, which is why it makes sense to put dataframe_step back in a step. See https://docs.google.com/document/d/1fMU3NzvyxJxpX5HaUGZzJU8XXzSpZTqVqTmXFLmzpcU/edit#heading=h.7m7oi4uppltu
Thus, if a dataframe step does not reshape the data, it belongs in a regular phase just fine. If it does, our safety checks in wrappers can detect it and error, telling the user it belongs in a ReshapePhase.
In this refactor:
What this sets us up for: