Outra forma de garantir isso em tempo de compilação é o tipo de retorno de cada método, mas esse caso é mais trabalhoso.
Você teria que criar N classes internas, que seriam devolvidas em cada step
ContractBuilder teria só um método que receberia a data inicial e que devolveria ContractStartedDateBuilder, que por sua vez teria um método que receberia o enddate e devolveria um outro objeto do tipo ContractEndedDateBuilder, um pra amount e outro pra criar o objeto... assim tu garante que sempre vai seguir a ordem, mas o trabalho é bem maior.