Let the former be a monotonically increasing (say 64-bt) integer, and the latter be a free-form string. This way, marketing folks are free to call one version "macOS 10.16 Big Sur", followed by "macOS 11.0 Big Sur Pro Max", "macOS 10.32 Pro SE", etc. w/o developers pondering over whether "Pro SE" > "Pro Max". As for API, maybe something like getProductVersion() for the internal version, and getProductName() for the external version. Heck, be facetious and let the latter return a string like "!!! DO NOT USE FOR VERSION COMPARISON USE getProductVersion() INSTEAD !!!\07\07\07macOS 10.16 Big Sur".
Yes, lazy developers will get it wrong, similar to how they use gettimeofday()[1] instead of clock_gettime(CLOCK_MONOTONIC, ...)[2]. In their defense, often software switch between versioning conventions such that what's the "right" thing to do is unclear.
[0] Such appropriation is everywhere. Don't get me started on how Porsche Taycan, an electric car, has a "Turbo" model. It probably doesn't even come with blinker fluid standard.
[1] https://pubs.opengroup.org/onlinepubs/9699919799/functions/g...
[2] https://pubs.opengroup.org/onlinepubs/9699919799/functions/c...