skip to content

Strata

Every library on the roster declares exactly one stratum. Not zero, not two — one. The declaration lives in a single total map in the hub’s own source, and “total” is not a description, it’s a build-time property: a roster member with no entry there is a build error by design, not a lint that happens to catch it later.

algebra,
aspects,
assemble,
bind,
class,
delivery,
dispatch,
graph,
identity,
inspect,
link,
memo,
merge,
prelude,
product,
program,
schema,
scope,
select,
settings,
types,
view,

Each of those twenty-two names is bound to exactly one of five stratum values in lib/mkGenLibs.nix’s strata map.

Four stratum values form an ordered chain: substrate < modules < aspects < framework. The fifth, retiring, isn’t a layer at all — it’s the state of a library whose content is moving into another member and off the roster. It sits outside the ranking, because ranking it would mean deciding where a thing that’s leaving belongs relative to things that are staying, and there’s no coherent answer to that.

publishedStrata = [
"substrate"
"modules"
"aspects"
"framework"
];
knownStrata = publishedStrata ++ [
"retiring"
];

At the current roster’s count: twelve libraries are substrate (the base layer — values, graphs, selection, evaluation), two are modules (the module system’s checking and merging halves), three are aspects (the aspect layer, built on the module system), and five are framework (above the stack rather than a layer of it — nothing may define substrate vocabulary in framework’s terms). Nothing currently sits in retiring; the bucket exists for when something does, and a library that’s there stays reachable on the flat roster rather than disappearing the moment it starts to leave.

No member may declare an input above its own stratum. A substrate library cannot depend on an aspects library; a modules library cannot depend on a framework library. That’s not a style preference — it’s what makes “substrate” mean anything: if a base-layer library could reach up into the aspect layer, there would be no base layer, just a graph of libraries that happens to draw a diagram in one particular order today.

A dedicated check walks that graph on every run. Exactly one upward edge is ruled through as a named exception rather than hidden: gen-schema, substrate by role, declares kinds whose fields are options and so is written in the module system’s language — reaching up into gen-schema’s neighbor, gen-merge, in the modules stratum. The check doesn’t soften the rule to let that edge pass quietly; it prints the exception, entry by entry, on every run.

palette
dark
light
↑↓ select apply esc close

Palettes adapted from Catppuccin (Macchiato) (MIT), Tokyo Night (Apache-2.0), gruvbox (MIT), Catppuccin (Latte) (MIT), Rosé Pine (Dawn) (MIT).