There’s a difference between these two senses of “automatic”, though.

An “automatic” update of a language-ecosystem build-time dependency package, is still curated by your (not usually fully-automatic) release-management process, like any other codebase change. With full CI/CD automation, some bot (e.g. https://dependabot.com/) notices that a dep has updated, and “proposes” a PR that updates your project’s lockfile; your CI buildbot then notices the new PR, and tries building that branch to see whether it compiles and all the tests pass; and, if everything looks good, it merges the PR into the main development branch. Even then, it’s now just merged into the ‘develop’ branch, and is not necessarily going to be a part of a cut release yet. A CD bot may put it into a QA environment from there; divert a percentage of traffic to it (ala https://github.com/github/scientist); and then maybe eventually make the call that it’s not hurting your metrics, and so switch the traffic fully over to it. But more often, there are usually humans in charge of that final cut-over switch, whoget to make a final call, before this kind of “automatic” update fully hits prod.

Whereas, with OS packages, there’s no CI/CD pipeline — the version number on the package (coupled with your auto-update config) is the “last line of defense” standing between the package and your production system. You can set up a mirroring QA environment that gets updates first; but this is effectively just “smoke testing” — you don’t really get to “run all the tests” for your entire OS and application layer over again, in light of e.g. a new libc, to “prove”—at least in some minimal sense—that things will be fine in prod. You just deploy the configuration, and observe that it’s “working.” Maybe you will have metrics on OS log volume or something similar; but OS package updates often introduce new spurious logs that you don’t care about, so this is a bad metric to track.

(Of course, you can do the QA traffic-splitting thing for your OS-package updates as well... but this means slowing the cadence of OS updates / bundling updates together so that you can gather enough data to say something about whether each new update-bundle is “working.” And if you bundle enough updates together, you’re effectively taking the reins of the OS from its maintainers, with the OS becoming just another part of your release-management process, i.e. with you effectively cutting whole-VM-image “releases.” Which somewhat removes the key advantage of automatic updates — especially automatic security updates, and especially especially automatic kernel security updates [ala https://ubuntu.com/livepatch]. You make yourself vulnerable to these discovered attacks in the interrim, in the name of stability.)

When you think about it, as long as you’re operating in “full paranoia” mode in both cases (as described above), then for the “build-time dependency” packages, all the stuff the CI/CD pipeline does kind of obviates versioning. An incompatible new version of a dep that breaks your software, will just be caught during the regular CI process. You may as well use the sort of timestamp+gitsha versioning that the OP proposes; nothing would really change. It’s only in the OS package case, where semver is getting you a benefit you wouldn’t otherwise get just from good release hygiene.