Ecosystem and tiers
The redefinition: stability comes from the architecture. The tiers separate what changes slowly from what changes fast, and the axis is who owns the promise, not age.
The idea
Section titled “The idea”Every big language faces the tension between “the core has to be stable for decades” and “the libraries have to evolve”. The usual answer is semver on everything and hope for the best, which treats “1.0 1.1” as if the version guaranteed the safety of the change, which is a half-truth.
How Makoto redefines it
Section titled “How Makoto redefines it”The ecosystem is organized into stability tiers, and the axis that separates them is not age nor area. It is how freely the contract can be touched (and, at the limit, who owns the promise):
- Tier 0, core (the language + the stdlib): the standards that engineering has not changed for half a century, like IEEE 754, TCP/IP, UTF-8, what a “linked list” means. It is add-only: you add, you never edit the observable contract (a bugfix that makes the implementation start matching the promise already made is allowed; changing behavior that someone depends on, no). The language itself is the bedrock, and editions are add-only taken to the syntax.
- Tier 1, official libs: what evolves because it is a specification, not an eternal standard. HTTP had
three versions, TLS turns, a regex engine swaps algorithm. Its own cadence (semver/changelog),
opt-in, zero weight until the
use. - Tier 2, frameworks (
web, the UI): more opinion, more churn. - Tier 3, third-party: the compatibility promise is someone else’s, and here the axis changes in nature.
The rule: tiers only depend downward. And there are two fine cuts that the time-axis hides:
- Closed set vs open roster.
collections(List/Map/Set) is tier 0 because it is a complete and closed set: there will never be a “fourth fundamental collection”.containers(B-tree, ART, deque, ring buffer) is tier 1 because it is a roster that grows, where each algorithm inside is frozen (tier 0 content), but the collection changes (tier 1). Same algorithm age, different tiers. - The tier cuts within a concept. UTF-8 is frozen (tier 0); the Unicode tables, which gain characters every year, are tier 1. The UTC/offset clock is tier 0; the IANA timezone names, which change with a country’s policy, are tier 1. The mechanism part stays on the floor; the mutable data part goes up a step.
And the module model that sustains this: mk.mod = lib (a reusable box with its own deps,
never compiled alone), mk.project = bin/composer (composes the tree, produces the artifact),
resolution by MVS (Minimal Version Selection).
The reasoning
Section titled “The reasoning”The question the tier answers is a single one: who promises that this will not break, and with what freedom? Age correlates (what has an untouchable contract tends to last decades), but it is just the symptom; the ruler is the contract. That is why the cut predicts decisions that had already been made by instinct (UTC in core, IANA opt-in/heavy): when the model predicts what you already did by good sense, it is a sign that it is real, not imposed. The immutability of tier 0 is that of the promise, not of the binary: the source fixes a security flaw, the promise does not retreat. And when the incompatible is inevitable, the migration tool (the slow-core with a mechanical escape) applies the correction, instead of the language forking.
Why not the alternatives
Section titled “Why not the alternatives”- Semver as the government of everything. It treats the version as if it guaranteed the safety of the change (“1.1 is breaking-safe”). It is a half-truth. Tier + add-only in the core is an honest promise about what can change and who owns it.
- Tier = age. “Tier 0 because it is old” is weak; a B-tree is as old as a list and even so it lives in tier 1. What matters is whether the contract changes.
- Everything at the same level of stability (early Go, Python 3). Without tiers, silent breaks in patches, or a painful transition when tier 0 forks. The layers isolate the churn.
- “Highest compatible version” to resolve deps. MVS chooses the minimum that satisfies, avoiding the diamond problem and making builds reproducible: you are not dragged into a new version without asking.
The concrete pain
Section titled “The concrete pain”The early Go ecosystem, before modules, where a go get could break your build out of nowhere. The Python 2
3, a tier 0 migration that cracked the community for a decade. The library that goes from 1.4 to
1.5 and breaks you, because semver promised what it could not keep. Each one is the lack of a
stability architecture: everyone at the same level, with no clear owner of the promise.
The mental model
Section titled “The mental model”Stability comes from the architecture: what changes lives higher up. The core is add-only (we are the owner of the promise, and the promise does not retreat); each step up turns faster, until the third, where the promise is someone else’s.
The accepted friction
Section titled “The accepted friction”Add-only means that the core carries forever what entered it: a bad decision in tier 0 is not removed, only worked around by addition (hence the ruler of only admitting into the core what is genuinely closed and fundamental). And MVS trades “always the latest version” for “the minimum that satisfies”, reproducibility at the cost of you having to ask explicitly to go up. These are the prices of a stability that is a promise, not a hope.
Next: 12 · Honest names