Регрессии это нормальное явление. Почему такое происходит в принципе - интересный сам по себе вопрос.
Регресс появляется когда добавление нового кода или изменение старого не учитывает всех задействованных частей программы.
Отсюда можно сделать вывод, чтобы минимизировать эффект от регрессии, нужно огранизовывать код так, чтобы при его изменении, можно было легко понять, на какие другие части логики это изменение влияет. Именно это является целью создания идеальной архитектуры приложения. Чтобы все было по полочкам. Чтобы доставая из шкафа полотенце, вам на голову не падала матрешка которая стоит на шкафу сверху (кто ее туда поставил, и почему - неясно, записку с комментариями никто не оставил)
Чтобы бороться с наваливанием кода в кучу - нужно чтобы кто-то следил за тем чтобы его не наваливали в кучу. Архитектор например. Архитектор это такой ландшафтный дизайнер для кода. Но нужен и садовник. Чтобы лужайки были зеленые, а огурцы не расли на грядке в перемешку с морковкой. Фреймворки конечно тоже отчасти справляются с этой задачей. Фреймворк для того в принципе и служит, чтобы для каждой части приложения была своя песочница. Мол, складывай вещи как хочешь но в коробки 40х50х30. Текстиль сюда, кухонную утварь сюда. Коробку подписать, занести в реестр. Как на складе.
Но ничто не защитит вас от того, что в коробки накидают не того что там должно быть. Надо проверять (тестирование). Выстраивать процесс таким образом чтобы ошибиться по халатности было трудно (архитектура). Чтобы было легко локализовать источник ошибки (логгирование). Систематично избавляться от сложности во всем (здравый смысл).