R1.05.2dual-version consistency collapsedesign

Shipping multiple versions in parallel collapses consistency

Aliases: dual version · two buttons · version skew · parallel implementations

What it is

Old Button and New Button running in the same product look like a smooth bridge. There is no longer one Button. Two APIs, two focus behaviors, two theme hooks, each team picking by its own upgrade speed. Dual-version shipping without a hard bound stops being a tactic and becomes the architecture: consistency does not catch up slowly — two grammars teach it apart at the same time.

The target is two implementations importable in the wild, not “a break needs a path,” and not “deprecation needs a date.” Paths and dates can be immaculate; if both implementations coexist without end, nobody learns which one counts.

Why it happens

Consistency depends on one name pointing at one contract. Split the import into pkg/button and pkg/button-next and the contract splits. One team stays on the old to hit a launch; another cuts to the new for a slot they need. The two meet on a page — dialog on the new, footer on the old — and spacing, radius, and disabled focus start to drift. A designer walking the product cannot tell whether a miss is an implementation bug or a version delta. The walk costs twice and concludes less.

Coexistence also contaminates contribution: does a bug get fixed twice, does a new variant land twice. Maintainers usually patch only the new; the old keeps its known defects on high-traffic pages, so “official” looks like one set while users hit the wounded set. Dual-track with no retirement pressure is not a bridge. It is permanent double rail.

Where it stops holding

Intentional long-lived dual tracks (stable versus experimental channels, desktop versus mobile packages) whose names, docs, and install entry points were split from day one are product-line cuts, not two ages of the same button. A build that compiles old exports into the new implementation, so runtime holds a single artifact, is not dual-version. A third-party plugin pinned to an old major that you cannot bump is an external constraint: isolate it (plugin sandbox) rather than let it mix with the app’s new button in the same DOM. Docs and demos that render both on purpose for contrast must be labeled as contrast, not copied as a product template.

Applying it

  • Cap coexistence: the second implementation may exist only as a time-boxed import. Main docs and scaffolding demonstrate one.
  • Forbid importing old and new in the same page tree of the main app. Mixed imports fail the build or the lint.
  • Land bugfixes on the implementation that will remain. The outgoing one gets safety patches only, and the changelog says so.
  • How to check: search the repo for the component’s import paths and count live implementations. More than one in the main app means consistency is already splitting. Pair screenshots of mixed pages; spacing and focus deltas should trace to two contracts, not to “someone wrote a bad style.”

Related

  • Same group: R1.05.1 A breaking change needs a migration path · R1.05.3 Deprecation needs an explicit date or release
  • Nearby: R1.13 Versioning and migration cost · R1.18 Adoption and compliance metrics
  • Search terms: dual-version consistency collapse · version skew · button-next

Cards in the same group

Quick Actions

Share

Share this page

ios_share

https://hci.top/en/handbook/R1.05.2