Static and dynamic¶
A feature is two different things depending on who asks.
Static is the question a tool asks of itself while it builds: which commands exist,
what a help screen lists, what completion offers, what a diagnostic inventories, what a
code generator scaffolds. Those answers must be fixed at construction, from the binary's
imports and the tool's own choices, so that --help is the same offline as online and a
CI run sees the same CLI as a laptop. Set.Enabled answers them.
Dynamic is the question a service asks per request: is this experiment on for this
user, has this kill switch been thrown. Those answers may come from a backend, may be
targeted at a subject, may fail, and need a fallback. Evaluator.Evaluate answers them.
The line is enforced by the descriptor, not by convention. A descriptor that does not
report IsDynamic is static-only, and no evaluator will return anything but its Set
state for it, whatever a backend says. A tool declares a dynamic feature the same way it
declares any other, so the same inventories know it exists, and its static state is its
fallback: the tool's own decision, made once, in the one place an offline default can
honestly live.
Set implements Evaluator with the static answer, so a service can be wired with a
Set today and take a Dynamic tomorrow without a call-site change. No vendor SDK enters
this module; each backend is an adapter module, so a tool links only what it uses.