Capabilities: what a place Whiskers runs can offer, one small trait each.
An adapter is a type that holds some ports and says which it holds by implementing the Has… trait of
each. Nothing obliges it to hold them all: the native binary holds every one, a Worker that serves only the
hubs holds three. What is served is then a question the compiler answers. whiskers-service builds a route
only on the capabilities it needs (Service::check requires HasJudge + HasClock, and an adapter without
them cannot call it), and whiskers-conformance selects the laws of a capability only for an adapter that
has it. There is no stand-in port and no "not configured" answer for a capability the adapter does not
have: the route is not there.
Each trait names the port's type and hands out a reference to it. The ports are not boxed: an adapter is a
build-time choice, and a Worker's futures cannot be Send, which a dyn with a Send bound would demand.
One household, one writer. Every stateful capability of one adapter must behave as if exactly one thing
at a time writes a household's state. How is the adapter's business: natively, locks in one process; on
Cloudflare, one Durable Object per household (single-threaded, so each merge is atomic by construction);
under celld, the same object, owned by exactly one node at a time. An adapter whose stateful capabilities
are not serialised together (the hubs on one writer, the allowance on another) is not an adapter: the
conformance suite's concurrency checks exist to catch it.
[Backend] is the name for "every capability", for the adapter that is complete (the native binary).
What Whiskers remembers.
The grown-ups' choices and the day's time. Besides its own sync route, the routes that apply a policy (the thinking window, the voice cap, the usage screen) read the household's choices from it.
The one running session.
The one append-only log of everything said.
The pictures that go with memories.
What may be spent: the thinking window and the day's voice characters.
Jev's decisions.
Text to vectors.
The natural voice.
The language model.
Every capability. There is nothing to implement: a type is a Backend exactly when it implements all the
Has… traits, so a capability added to this list is a compile error in every adapter that claims to be
complete, until it has it.