This is what usually happens if you let incompetent people make design decision: they stay with the first and worst version forever.
Right now I'm in the process of leaving a company where this happened over and over again. The company's product and design aspects were always neglected in this specific way: whenever a problem was discovered its solution was assigned to whoever would write the code to solve it. That's it. The QA would be notified a week or two before the release and after the solution was "finished". The QA would then not be allowed to even comment on the overall design, only the superficial bug reports were allowed to go through.
Needless to say the product's code-base is a dumpster. The morale is low because it's a daunting task to deal with this dumpster on a daily basis. Now, even if you wanted to, you wouldn't have a budget to fix the previous design mistakes because of the layers of more mistakes that were added on top of them due to the low morale and lack of budget / lack of procedure for making better design decisions. The only thing that keeps the product afloat is its uniqueness in a rather niche field and the backing of a large company that acquired it, but doesn't really depend on it and has no time for a thorough audit.
> This is what usually happens if you let incompetent people make design decision: they stay with the first and worst version forever.
This is what usually happens when you confuse the decisions that mattered from the ones that didn't. It's like back before 'just use a linter' was the solution to code formatting. You'd start a project, you'd have the 'code style meeting' and everyone would bash themselves into the rocks of whitespace and bracket placement, and never get to things like code organization, structure, and naming of things.
So then you end up with code that uses the same noun in three places to mean 3 different things and uses it as a verb in a fourth.
You only get so many opportunities to really change the direction the boat is steering and you can wear out your welcome trying to exceed it. If you get some things right they'll let you do a few more.
Well, I had to be more specific instead of trying to be dramatic...
The thing is, nothing in the suggested procedure addresses the problem of how you are supposed to distinguish the decisions that matter from those that don't. Whoever came up with this idea must've thought that it's trivial to the point it doesn't need solving, but it's the opposite, unfortunately.
Also, FYO, linters aren't responsible for code formatting. It's the formatter's role. Linters advise on style. I.e. the problem of bracket placement is not solved by using linters, an example of problem that is solved by linters is the maximum number of properties a class is allowed to have.
But the meetings about formatting or using / disabling linter rules still happen. Having tools to do that didn't make the problem go away. What did happen, however, is something more like natural selection. The increased volume of newcomers which the field saw up until maybe five or so years ago were mostly steered in a particular "winning" direction. So, today, naturally, you have most people agree on a set of rules to follow because the majority came from the same background. You need a bunch of old-cadgers to work together on a project for there to be a feud over styling rules.
I would have assumed code reviews would have sussed out those issues earlier in the cycle?
To comment on my concrete (and quite miserable) situation, here's how it went (and does, even worse with the advent of AI, to this day):
* A report comes from the field (to the support team) that something is broken (or highly desired by the customer).
* The support team assigns the ticket to the lead engineer.
* The lead engineer writes the code and after a quick battle with CI pushes it all the way to the customer in need.
* Since it's the lead engineer, he has the authority to merge PRs w/o consulting anyone, which is what he does. You just pull the changes and marvel at them, or at the sunrise, whichever you like best. The "urgency" is used as a justification to skip the due process.
Now, when AI came into play, two horrible things were added into the mix:
* AI audit and code review. The audit is a 50/50 chance between finding a real problem vs misunderstanding of the purpose of the code or the context in which it is executed. The AI will also come up with a solution that is either completely wrong, unnecessary or touching too many things for a human to track. Code review acts in a similar way, except, technically it fills the role of a human reviewing the code, so it gives a sense of false security to anyone making changes.
* AI generating code that is hard for humans to follow. First and most obvious problem is the volume. In minutes AI generates changes that will take months of effort to review. But this is only the beginning of the problem. When reading code written by humans, another human builds a model of the author's approach, ability, intention and permissions. When it comes to AI, these... let's call them "dimensions" are all over the place. The generated code you read may seem very plausible for a while until you stumble into a crucial functionality that completely invalidates everything you've learned about the change so far. The change may make unnecessary segues into the territory it was never meant to touch.
So, even when there are code reviews, they now miss a lot more than they used to when only humans were writing code.
Also, and this is a pathologically bad, but a very common practice: the reviewer's name is missing from the record. You run git-blame and only see the author, not the reviewer. When things go down, the author takes the heat and the reviewer is nowhere to be found. Subsequently, reviewers don't feel like they need to care as much about the outcomes.
Oh, and one more thing. To be effective at reviewing anything you'd want to try things... as in to test them. Perhaps come up with some idea about what things must happen and what things absolutely must not. But where do you find those? Usually... in a design document, s.a. a PRD, but in the case where that design (allegedly) was solely in the head of the person writing the code, how do you even know if the behavior you conjecture the code has (because there are no tests) is the desired one?