Here’s my take. Semver is crucial in our modern “dependency management” era to imbue meaning into versions. It is the only thing that gives common ground across all the different pieces that go together to make up an “app”.
The most important piece of Semver is the breaking changes: using `^4.0` notation in Composer *must guarantee* that an update won’t break your app.
Now the caveats… Though it isn’t stated in the docs, I believe Semver is based on the principles of strong dissociation between the code’s internal work and it’s public API. Since Semver *only applies to the public API* there is significant work that will always be done to the internal code without affecting versioning. Here’s our first big problem: CI4 has very weak boundaries between internal code and public API. Another way of saying this: way too many classes, methods, and properties are “public” or “protected” when they should be “private” or “final” or “internal”.
What does this mean? This means that changing the signature of an insignificant protected method counts as a change to the public API and thus is a “breaking change”. Does this mean we *absolutely cannot* make these changes? No, but every one must be accompanied by a “BREAKING CHANGE” warning in bold User Guide and, to the casual reader, makes CI4 look bad.
So how do we fix this? The most important fix is to go to the root and establish strong internal/public boundaries - but this would be such a large and sweeping backwards-incompatible change that it would require a major version (hint: this is coming in version 5). So we are left with small and deliberate changes, identifying methods and areas of the code that are not as they should be and making those breaking changes with caution and documentation. We still avoid deliberate changes which would under all normal circumstances result in a major version.
One last thought… Semver has a bit of an unusual definition for “bug fix”:
> A bug fix is defined as an internal change that fixes incorrect behavior.
I got to CI4 after most of the initial code was written. I stand on the backs of developers who volunteered lots of hard work and many hours to write that code - most of whom are not around anymore. In my opinion, there is a fair amount of “incorrect behavior” in the way things were originally written (not faulting anyone, we all have our weaknesses). So I ponder this question myself and invite you to as well:
Can we modify intentional behavior that we disagree with and release it as a bug fix?