Semantic versioning is really only suitable for code APIs. It’s designed to communicate the cost of upgrading a package to programmers: if a release contains breaking changes, you may need to modify your code to ensure everything continues working.
For user-facing software, this concept doesn’t translate directly. If you change the location of a button in a desktop app, the program still works; the user simply has to adjust to the change. Large interface or behavior changes can be considered “breaking” in a loose sense, but the impact is far less severe than in code APIs.
The key takeaway is that versioning should reflect who or what consumes your system. Code is brittle and cannot easily handle breaking changes, so semantic versioning makes sense there. Humans, on the other hand, are more flexible and can adapt to changes with minimal disruption.
For software designed for people, a simple approach is to use a unique timestamp as the version number for each release, paired with accompanying media that explains the update. Users can then decide whether or not to adopt the new version based on the provided information.
So whenever it's time for a version I just go into my linux terminl and run:
date -u +"%Y.%m.%d.%H.%M.%S"
a better spec
The core problem with semantic versioning is that it collapses many independent kinds of change into a single linear number. A major version bump signals a “breaking change”, but that breakage is conditional: it only applies if you rely on the specific surface area that changed. Consumers are therefore forced to manually investigate every major upgrade, even when the subset of behavior they care about is entirely unaffected.
This makes major versions a pessimistic signal. They encode the worst possible compatibility outcome, not the actual outcome for a given consumer. As a result, automation stops at major boundaries and human intervention is required even when no meaningful incompatibility exists.
Version identifiers
Each release is identified by a monotonically increasing, globally unique timestamp:
YYYY.MM.DD.HH.MM.SS (UTC)
These identifiers encode ordering only. They carry no semantic meaning. All upgrade decisions are delegated to an update system that reasons about changes relative to consumer-defined requirements.
The update system
A conforming implementation must provide an update system (a program or service) capable of evaluating upgrades between versions. From the consumer’s point of view, this system is the only interface they interact with. The internal mechanisms by which it detects, infers, or reasons about change are explicitly out of scope for this specification.
The update system defines which properties it is capable of tracking. Only properties that are actively tracked by the update system can be used as requirements or guarantees.
Consumer requirements
A consumer supplies a set of requirements describing what must remain true across upgrades. However, a requirement is only valid if the update system explicitly tracks the corresponding property.
By default, the update system is required to track and guarantee API compatibility only. All other properties are optional and must be explicitly supported.
If a consumer cares about a property that is not tracked (for example runtime performance, memory usage, or latency), the consumer must request that the update system provide tracking and guarantees for that property. Until such tracking exists, no guarantees are implied.
Examples of consumer requirements include:
- Preserve compatibility with existing code (API stability)
- Allow breaking API changes
- Prevent runtime regressions (if runtime is tracked)
- Prevent increases in memory usage (if memory usage is tracked)
Tracked properties and continuity
Tracked properties are not assumed to be permanent. If the update system tracks a property for some versions and later stops tracking it, then all subsequent versions provide no guarantee for that property.
In such cases, consumers that depend on the property must treat the last version for which the property was tracked as the highest safe upgrade point, unless they explicitly choose to waive that requirement.
The absence of tracking is equivalent to the absence of a guarantee.
Upgrade evaluation
In order to update a given package without manual interention, the update system evaluates versions in chronological order and determines the highest version that satisfies the consumer’s declared requirements.
Evaluation stops immediately before the first version that would violate a requirement, either due to a detected change or due to the loss of tracking for a required property.
Properties and guarantees
For properties that cannot be fully inferred automatically, producers may optionally provide explicit guarantees for specific releases. These guarantees are only meaningful if the update system recognizes and tracks the corresponding property.
If a guarantee is absent, withdrawn, or no longer tracked, no assumption is made about that property in future versions.
Upgrade policies
Consumers define upgrade policies in terms of requirements rather than version numbers. Examples:
- Update to the newest version that preserves API compatibility
- Update to the newest version before any runtime regression occurs
- Always update to latest, ignoring all guarantees
Version numbers are no longer decision points. They are merely coordinates in time.
Summary
This specification replaces semantic versioning’s coarse, producer-centric signals with a consumer-centric upgrade system. Versions encode order, not meaning. Meaning is supplied by consumer requirements, constrained by what the update system actually tracks, and enforced automatically. Guarantees exist only where tracking exists, and disappear when tracking disappears.