A prime directive whenever you decide to leap to a new technology/methodology/discipline is to make sure that you have added value to your repertoire. You should GROW, not CHANGE. You should trash what does not work, but you should not trash apples for oranges.
Like Robert Martin says: "You should not only absorb why waterfall is bad, you should also know why it was good (at times)".
I have started to appreciate certain indicators when it comes to whenever a requirement spec is justified.
Notice the phrasing above; I put the onus of waterfall applicability on the person wishing to present me with a requirement spec. The burden of proof is on the person professing waterfall, but it defaults to Agile.
In his book "Clean code", Uncle Bob quotes several nestors within our field as to what their opinion is on clean code. Ward Cunningham comes with one of his characteristically apparently annoyingly redundant comments:"When the code is pretty much what you expect".
At first glance this is seems like a cop-out of answering the real question, but upon closer reflection, there are subtle brilliances within this very simple answer. Reading clean code should not make you pause, there should be little "flavours", nothing should feel forced, there should be no need to mentally context switch within a single class, the name of the class and class members should give you a reasonably good opinion as to what lies behind it.
For all my thoughts on the little nuggets of factors that combine into a good requirement specification, it basically boil down to the same:
When writing and reading it is all but a formality, then it is a justified specification.
The fabled animal "irreducably complex infrastructure" may still really exist, but you should still have a go at it with real tools before calling in the medium.