Running Software on Software Youâve Never Run
I love a good look at modern practices around semantic versioning and dependency management (Rick Hickeyâs talk âSpec-ulationâ is the canonical one I think of).
Niki recently wrote a good âun at tonsky.me called âWe shouldnât have needed lockfilesâ.
What struck me was this point about how package manifests allow version ranges like ^1.2.3 which essentially declare support for future versions of software that havenât yet been written:
Instead of saying âlibpupa
1.2.3depends on liblupa0.7.8â, [version ranges] are saying âlibpupa1.2.3depends on whatever the latest liblupa version is at the time of the build.âNotice that this is determined not at the time of publishing, but at the time of the build! If the author of libpupa has published 1.2.3 a year ago and Iâm pulling it now, I might be using a liblupa version that didnât even exist at the time of publishing!
The funny thing is, we use version ranges only to go freeze them with lock files:
version ranges end up not being used anyway. You lock your dependencies once in a lockfile and they stay there, unchanged
In other words: we avoid locking ourselves to specific versions in package.json by using version ranges, only to then go lock ourselves to specific versions in package-lock.json â lol!
I mean, thatâs funny when you think about it.
But to go back to Nikiâs earlier point: version ranges let us declare to ourselves that some code that exists today is compatible with some other future code that has yet to be written.
This idea allows us to create automated build systems that resolve to an artifact whose dependencies have never existed before in that given combination â let alone tested and executed together in that combination.
Now I get it, semantic versioning is an idea not a guarantee. But itâs also pretty wild when you think about it â when you encounter the reality of how semantic versioning plays out in the day-to-day world of building software.
I guess thatâs a way of acknowledging out loud that we have normalized shipping production systems on top of the assumption that untested, unwritten combinations of software will behave well together â if not better, since patch updates fix bugs right?
And thatâs not even getting into the security side of the equation. Future versions of packages have no guarantee to be as safe as previous ones, as weâve seen with some of the npm supply chain attacks which rely on version ranges for their exploits. (Funny, isnât it? Upgrading to the latest version of a package can get you into trouble. The solution? Upgrading to the latest version of a package.)
Anyhow, this all gets me thinking that version ranges and dependency management were the gateway drug to the non-determinism of LLMs.