What a @stores row may hold: a keyed Store or a Unit. S is the
state a read of the regent returns — the keyed collection for a store,
the value for a unit — so one typed lookup serves both kinds.
A POSITION in the queue that answers ledger.at(...) with its typed
Handle — the spec instance carries the handle type, so the lookup is
fully typed with no name in between. Every regent kind is a position
(store → StoreMemory, unit → UnitMemory, guard → GuardMemory), and
the two positions nobody declares are the static sentinels:
The message bus — the RICH tier's transport. Dispatch messages through
guards to typed subscribers. Transport-agnostic: feed it from WS, HTTP, a
local DB, or a local optimistic dispatch(..., optimistic: true).
Decoupled from canon and from Flutter; a StoreMemory subscribes to it,
and a riverpod notifier can subscribe via on too — neither owns the other.
The cursor intervals an authority has covered — a plain folded VALUE,
pure and axis-blind (the consumer decides what C means: a DateTime, an
int, a name). Absence WITHIN a covered interval is a fact ("gone");
absence outside is silence.
A PURE judge standing at its row of the queue: every traversing message
of the M family is submitted to judge, whose returned set IS its
verdict — one verb for every shape of judgment:
One judgment's full story, emitted AFTER the verdict ran: the submitted
message and what the guard launched for it, atomically — for a Veto,
an empty verdict IS the block. Observation only (ledger.at(spec));
the flow itself never depends on it.
The live handle at a guard's row (ledger.at(const CachedGate())):
the judged input and the verdict, observable — a judge holds no state,
so its memory is pure story. Plural members are streams, all derived
from the atomic events:
One LAUNCH — the element of a guard's verdict. A guard at index x may
target exactly TWO indices, the only two that preserve the system's
theorem (no row ever sees a message that skipped a guard above it):
A FACT. The journal stores it, replay
re-delivers it — so it must never mutate after construction. The
annotation makes the analyzer enforce final fields on every subclass.
A READ RESOLVER for a merge edge (user.merge(viewer, const ViewerSupportsUser()) in the entities graph): the SOURCE store's state
answers the TARGET surface's per-key reads at the source's OWN identity —
S extends Identifiable<K> IS the claim; there is no key method anywhere.
Marks a method (or class) as PURE — its body may read only its parameters,
locals, pattern-bound variables, and compile-time constants, and may call
only other pure functions. No ambient or mutable state, no clock, no
randomness, no I/O. Purity is what makes a fold deterministic and therefore
replay-able: replay(a) == replay(b) is a law only because the folds
between cannot reach outside their arguments.
The app as a VALUE: an ordered set of regents plus merge edges. A graph
IS a regent, and a regent is a one-row graph — Ledger.root takes a
single Regent, so the smallest ledger is Ledger.root(const NavUnit())
and the largest is a const tree:
A REGENT — a row of the ledger — anything that occupies a row of the regents
enum: stores, units, guards, vetoes. Row order is traversal order: a
message walks the rows top to bottom.
The PURE, const registry descriptor: how a message folds into an entry's
state. No mutable state, no ref, const — so it can sit in a spec. The live
store (StoreMemory) is created separately and wired to a Bus.
One fold's full story, emitted by a store AFTER the reduce ran: the cause
and its consequence, atomically — an effect filtering these can never race
the fold. Filters recover every narrower feed: structural (the list
shell), changed.contains(id) (per key), a before/after delta (state
TRANSITIONS), a msg-type check (post-fold message observation).
The live store for a Store: the folded collection driven off a Bus,
plus read-time merge edges and the change/event feeds. It holds NO other
state — optimism, in-flight status, freshness, and settlement all live in
consumer ROWS (docks, in-flight units, coverage), where they replay.
The UNIT sibling of Store: one value, cardinality one — for entities
whose identity is the session (the wire sends their facts KEYLESS: a
viewer profile, a requests+unseen state). Same purity contract.
The UNIT form of Projection — a unit-target merge edge
(viewer.from(viewerPending, const ApplyPending()) in the regents
merges set): the SOURCE unit's state answers the TARGET unit's read.
Keyless — a unit has cardinality one, so the edge always applies;
resolve no-ops itself when the source carries nothing. Read-time only:
the fold and guards' read never see it.
Entities are VALUES: folds produce new instances; a mutated entity
corrupts before/after events and optimistic refolds — enforced here for
every class that wears the mixin.
Pure sugar over a UNIT's post-fold event stream — the recurring effect
idioms as verbs. Extensions on the STREAM (not the memory), so they
compose after any filter and over replayed feeds alike.
The state the WHOLE ledger folds from order — its replay. Builds a
pure ledger from root (a Regency or any single regent), folds the
messages synchronously, and returns every regent's state keyed by SPEC
INSTANCE — z[const Todos()]. Deterministic: the folds are pure, so the
same messages always yield the same snapshot — replay is the operation
purity buys you.
A guard's view of the world: this ledger's own state, looked up by
regent IDENTITY — read(const BrowseDeck()), read(const AuthMachine()).
Const canonicalization makes the constructor expression the regent's
canonical NAME: const X() written in a judge IS the instance the row
holds (same class, different args = a different regent; two rows may not
hold identical instances — enforced at registration). Bound to the ledger
the guard stands in, so a replayed ledger reads itself. Throws when no
row holds the instance (wrong args, or a missing const).