symfonic.services.switching.values¶
values ¶
The values a switch decision is made of (CUT-SS, CUT-RB, CUT-AIR).
Everything here is a frozen, hashable value. That is deliberate: a generation vector that could be mutated after an invocation captured it would make CUT-SS-4's "one invocation observes exactly one epoch" unenforceable by anything stronger than convention.
BundleBinding
dataclass
¶
BundleBinding(bundle_id: str, epoch: int, generation_vector: GenerationVector, freeze_state: FreezeState = NO_FREEZE, source: str = 'release-static', fetched_at: float = 0.0, stale: bool = False)
DMC-1 — what a BindingSource answers with.
source is one of release-static, control-plane or
local-override (CUT-PIN-3), which is what makes "where did this
binding come from?" answerable in a diagnostic without guessing.
FreezeState
dataclass
¶
FreezeState(freeze_epoch_id: str | None = None, frozen_legacy_vector: GenerationVector | None = None, retiring: frozenset[str] = frozenset(), created_by: str | None = None, approved_by: str | None = None, created_at: float = 0.0)
SCP-FRZ-1 — the retirement-freeze epoch object, or its absence.
retiring is the set of generation ids the freeze disables for new
admissions. It is computed once, when the freeze is committed, so a later
vector change cannot silently widen or narrow what the freeze barred.
bars ¶
The retiring generations this vector would newly admit work onto.
GenerationVector
dataclass
¶
CUT-RB-3 — {capability_or_port → generation_id}, canonically ordered.
Stored as a sorted tuple rather than a mapping so two vectors built from
differently-ordered dicts are the same value, compare equal, and hash to
the same vector_hash. Ordering is the whole reason the hash is stable
enough to travel inside a checkpoint envelope.
InvocationPin
dataclass
¶
InvocationPin(bundle_id: str, epoch: int, vector_hash: str, source: str, stale_binding: bool = False, freeze_epoch_id: str | None = None)
The travelling half of a binding: what a checkpoint or token carries.
A pin names an epoch and a vector hash, never the vector's contents. A resuming worker resolves the contents from its own binding source and refuses if they disagree, so a pin cannot smuggle an unvalidated vector across a process boundary.