C.W.K.
Stream
Lesson 05 of 05 · published

Six Version Domains That Move Alone

~13 min · self-contained, versioning, compatibility, architecture

Level 0Reel Novice
0 XP0/39 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"Product, bundle build, state schema, URL protocol, libmpv build, and golden-corpus revision each advance for their own compatibility reasons."

The One-Number Fallacy

It's tidy to imagine an app has 'a version.' It doesn't. Ashen Reel has at least six things that carry a version, and each of them changes for a completely different reason. Force them all onto one number and you get one of two failures: either you bump the product version every time you repin a dylib (false churn that means nothing to the user), or you quietly change the deep-link grammar without anyone noticing a compatibility break (hidden breakage that means everything). One number can't be honest about six independent kinds of change.

Six Domains, Six Reasons

The fix is to name each domain and let it advance on its own clock:

  • Product version — the visible release, owned by cwk-product.json and advanced through Firelink. This is the number a human means by 'what version.'
  • Bundle build number — a deployment counter that ticks on any shippable build. A tally, not a story.
  • State schema revision — bumps only when the local SQLite shape changes and a migration is needed.
  • URL protocol version — bumps only when the cwkashenreel:// handoff grammar changes.
  • libmpv build — advances when the embedded engine is repinned to a new build.
  • Golden-corpus revision — advances when the required-media matrix changes.
One version per compatibility domain — never one number for all. A version number answers 'is this compatible with that?' Different pairings ask that question about different things — the deep link, the database, the engine, the release — and each deserves its own answer that moves only when its own compatibility actually changes.

The whole scheme fits on a card, and keeping the card is what stops the conflation:

The product version is canonical and singular. Exactly one source — cwk-product.json — carries the visible product release, and display surfaces add the 'v.' Package versions, bundle build numbers, schema revisions, and Git commits are NOT competing product versions; treating any of them as 'the version' is how a build number ends up on a marketing page. One canonical product number, many private compatibility counters.

Why Separation Is Kindness to Future-You

Independent version domains are a gift to the person debugging this in a year. When something breaks, the versions tell a precise story: the schema is at rev 4 but this database is rev 3, so migrate; the deep link says protocol 2 but this build only speaks 1, so reject. If all six were mashed into one number, every one of those diagnoses would be a guess. Naming the domains turns 'it's version 1.0.0, why doesn't it work?' into a set of specific, answerable compatibility questions. That's the whole track's lesson in miniature: honesty about what's actually independent makes the system legible.

Code

Six version domains, six reasons to advance — never collapse them·text
DOMAIN          SOURCE                   BUMPS WHEN...
------          ------                   -----------
product         cwk-product.json         Dad ships a visible release (Firelink owns)
bundle build    Info.plist build number  any deployable build (a counter, not a story)
state schema    SQLite schema revision   the local DB shape changes (migration needed)
URL protocol    handoff grammar version  the cwkashenreel:// grammar changes
libmpv build    pinned dylib manifest    the embedded engine is repinned
golden corpus   corpus manifest revision the required-media matrix changes

// Repinning libmpv does NOT bump the product version.
// A product release does NOT force a schema migration.
// Each domain moves on its own clock, for its own compatibility reason.

External links

Exercise

List every 'version' in a system you work on — the product version, an API version, a database schema version, a config format, a protocol, a data-file format. For each, write the ONE reason it should bump. Then find two that are currently forced to move together but change for different reasons. Splitting them: what false churn or hidden breakage does that separation remove?
Hint
Each version number answers a compatibility question about one specific thing. If two of your versions always move in lockstep but represent different compatibility contracts (say, 'the API shape' and 'the release'), you're either bumping one for no reason or hiding a break in the other. Give each contract its own number that moves only when that contract changes.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.