Clarifying my use of the open/closed principle:
You are correct. You can take a strict view of the open/closed principle, understanding that any change at all is a potentially breaking change. And that is a useful principle to keep in mind.
However, if you can’t change existing source code at all, you can’t fix bugs. You can’t easily adapt designs to new use-cases. This is totally legit interpretation for some use-cases (which is why there are bugs in the JavaScript spec that will never be fixed, so we don’t break the existing web), but it slams the door on a lot of maintenance that we regularly conduct in the day-to-day process of building applications. Being hard-nosed about the open-closed principle can put the brakes on a lot of legitimate software development activity, and that is not useful.
There is a looser interpretation which is more generally usable:
The essence of the open/closed principle is that we should minimize the number of changes required to add new features to the software.
Open for extension means that we should be able to add new features or components to the application without breaking existing code.
Closed for modification means that we should not introduce breaking changes to existing functionality, because that would force you to refactor a lot of existing code, and in the case of a public API, would probably break a lot of software consumers that are outside your sphere of knowledge or control.
Getting nit picky about the particular details of how the open/closed principle works misses the point. In both interpretations, it works as a general design guide that is not tied to any particular language or technology, and it applies equally to functions, classes, and even compiled binaries and deployed SaaS APIs.
If you can’t see past one rigid interpretation, you miss out on how it can be more broadly applied in equally useful (in this case, I’d argue more useful) ways.