"Agreed, but then we come back to the fact that we might refactor a 1997 codebase differently in 2004 than in 2017."
Well, if the original code is of the worst kind of a mess, Feather's circa 2004 collection of methods to make it more understandable but functionally the same work just fine for the first part of the refactoring. In my experience this is the most difficult part as well. To what dialect of the language the code is ported after it is understandable, is a relatively trivial syntax transform after this.
I speak from experience from having recently had to implement features to a production codebase with millions of lines of code, some of which date back to Fortran, and that took the final step of evolving into C++ sometimes in the late 90's.
I prefer the definition of legacy code that it's any code that does not have unit tests. In this case every transformation to a production codebase needs to retain the original behavior - without exact understanding what that behavior is.
I think this comment should have been my original response to this thread instead of the relatively cheeky responses I wrote earlier.