Correctness preserving program refinements: Proof theory and applications