Documentation
¶
Overview ¶
Package routing parses route selector strings and expands them into ordered attempt candidates.
Grammar (v1): model-only, backend:model, backend.instance:model, failover (a|b|c), weighted ([weight=N]a^[weight=M]b), [first] on weighted branches, parallel (a!b!c) with per-leg [handicap=N] and [ttft_timeout=N], and ?query parameters. Parallel and weighted operators cannot be mixed in the same arm; failover (|) of parallel groups is allowed (a!b|c!d). The planner applies exclusions, optional health filtering, session first-request rules, and deterministic weighted selection via an injected RNG.
Index ¶
- Variables
- func ApplyModelOnlyBackends(sel *Selector, defaultBackend string)
- func ApplyNativeModelIDs(sel *Selector, resolver NativeModelResolver)deprecated
- func BackendIDsReferenced(sel *Selector) []string
- func BindNativeModelIDs(sel *Selector, resolver NativeModelResolver) error
- func CandidateEqual(a, b AttemptCandidate) bool
- func CandidateSetsEqual(a, b []AttemptCandidate) bool
- func CheckContinuationCandidate(constraint ContinuationConstraint, candidate AttemptCandidate) error
- func ComposeInitialCandidates(raw string, aliases *AliasResolver, defaultBackend string, ...) ([]AttemptCandidate, *Selector, error)
- func DefaultBackendFromRouteSelector(defaultRoute string) (string, error)
- func FilterRoutePrefixes(prefixes []string) []string
- func IsDirectPrimary(sel *Selector) bool
- func RejectUnknownBackends(sel *Selector, known map[string]struct{}) error
- func SelectorHasEmptyBackend(sel *Selector) bool
- func SelectorHasRequestSizeConstraints(sel *Selector) bool
- func ValidateExecutionComposition(sel *Selector, classes BackendExecutionResolver, ...) error
- func ValidateModelAliases(rules []ModelAliasRule) error
- func ValidateModelAliasesConfig(cfg *config.Config) error
- func WithNativeModelResolver(ctx context.Context, resolver NativeModelResolver) context.Context
- type AffinityMode
- type AliasResolver
- type AttemptCandidate
- type AttemptGroup
- type BackendExecutionResolver
- type BackendExecutionResolverFunc
- type CandidateAdmissionCheck
- type ContinuationConstraint
- type FailoverAlt
- type GenerationSelectorValidator
- type ModelAliasRule
- type ModelBinding
- type ModelBindingKind
- type NativeModelResolver
- type Parallel
- type ParallelBranch
- type PlanOptions
- type Primary
- type RequestSizeConstraint
- type RequestSizeEstimate
- type Rng
- type RoutingScenarioSpec
- type Selector
- type SessionRoutingState
- type UnsafeExecutionCompositionError
- type Weighted
- type WeightedBranch
- type WrongBackendCanonicalError
Constants ¶
This section is empty.
Variables ¶
var ( ErrContinuationCandidatePinned = errors.New("routing: continuation candidate is pinned") ErrContinuationNativeMismatch = errors.New("routing: continuation native lineage mismatch") )
var ErrInvalidSelector = errors.New("routing: invalid route selector")
ErrInvalidSelector reports a syntactically invalid route selector.
var ErrNoEligibleCandidate = errors.New("routing: no eligible route candidate")
ErrNoEligibleCandidate means every candidate in the relevant scope was excluded or unhealthy.
var ErrUnknownBackend = errors.New("routing: unknown backend")
ErrUnknownBackend reports a compiled selector that names a backend identity not present in the current generation's side-effect-free registry view.
var ErrUnsafeExecutionComposition = errors.New("routing: unsafe backend execution composition")
ErrUnsafeExecutionComposition is the root sentinel for unsafe selector composition.
var ErrWeightedTotalTooLarge = errors.New("routing: weighted branch total too large")
ErrWeightedTotalTooLarge means the sum of effective branch weights exceeds math.MaxInt (cannot pass safely to the RNG) or overflowed int64 during accumulation.
var ErrWrongBackendCanonical = errors.New("routing: canonical model not registered for leaf backend")
ErrWrongBackendCanonical is returned when route planning binds a canonical that exists only on a different backend than the leaf's backend.
Functions ¶
func ApplyModelOnlyBackends ¶
ApplyModelOnlyBackends sets Primary.Backend to defaultBackend wherever it is empty. defaultBackend must be non-empty; otherwise this is a no-op.
func ApplyNativeModelIDs
deprecated
func ApplyNativeModelIDs(sel *Selector, resolver NativeModelResolver)
ApplyNativeModelIDs is retained as a deprecated alias that binds NativeModel without rewriting Model. Prefer BindNativeModelIDs; wrong-backend errors are dropped.
Deprecated: use BindNativeModelIDs and handle ErrWrongBackendCanonical.
func BackendIDsReferenced ¶
BackendIDsReferenced returns every literal (non-model-only) backend ID embedded across sel's failover alternatives, weighted branches, and parallel branches, in selector order. Used to validate a candidate default route or alias replacement against the candidate backend set before publication (req 9.2). A nil selector returns nil.
func BindNativeModelIDs ¶
func BindNativeModelIDs(sel *Selector, resolver NativeModelResolver) error
BindNativeModelIDs sets NativeModel on every selector leaf from the request-bound resolver without overwriting Primary.Model (logical/canonical identity). Wrong-backend canonical leaves return a typed error (fail-closed). Unknown raw/native leaves keep NativeModel empty (compatibility pass-through). Params, weights, handicaps, TTFT, affinity, and selector identity are untouched.
func CandidateEqual ¶
func CandidateEqual(a, b AttemptCandidate) bool
CandidateEqual reports whether two AttemptCandidates have identical routing identity, including backend, model, native model, isParallel, handicap, markedFirst, role, and selector key.
func CandidateSetsEqual ¶
func CandidateSetsEqual(a, b []AttemptCandidate) bool
CandidateSetsEqual reports whether two candidate slices match in exact order and membership.
func CheckContinuationCandidate ¶
func CheckContinuationCandidate(constraint ContinuationConstraint, candidate AttemptCandidate) error
CheckContinuationCandidate rejects a candidate that cannot safely replay a provider-bound record. Canonical requirements remain available to the normal admission check; this check only enforces exact lineage/pinning.
func ComposeInitialCandidates ¶
func ComposeInitialCandidates( raw string, aliases *AliasResolver, defaultBackend string, classes BackendExecutionResolver, policy config.ExecutionCompositionPolicy, resolver NativeModelResolver, ) ([]AttemptCandidate, *Selector, error)
ComposeInitialCandidates runs the full canonical routing composition sequence: 1. Selector compile (trim, alias resolution, parse, model-only defaulting, and unresolved-model-only rejection). 2. Execution composition validation under the active generation policy. 3. Request-bound native model binding (fail-closed on wrong-backend canonical). 4. Initial candidate extraction in exact order and membership.
It is pure and side-effect-free: no B-legs, no I/O, no live store mutation.
func DefaultBackendFromRouteSelector ¶
DefaultBackendFromRouteSelector extracts the backend id from a configured default route (for example "openai-responses:gpt-4o-mini"). The route must contain at least one primary with a non-empty backend (not model-only).
func FilterRoutePrefixes ¶
FilterRoutePrefixes trims, drops invalid (empty, colon- or slash-bearing), dedups, and sorts backend route-selector prefixes. Shared by runtime bundle composition and frontend PrefixSet construction so the validation rule lives in one place. A prefix is the "<prefix>:" segment of a route selector; it must not itself contain ":" (which would make it a full selector) or "/" (which collides with provider-namespace model syntax).
func IsDirectPrimary ¶
IsDirectPrimary returns true if the selector contains exactly one failover alternative and that alternative is a single direct Primary (not weighted or parallel).
func RejectUnknownBackends ¶
RejectUnknownBackends reports referenced backend IDs absent from known. A nil known set means identities were not available without I/O; the check is skipped. An empty (non-nil) set rejects every explicit backend ID.
func SelectorHasEmptyBackend ¶
SelectorHasEmptyBackend reports whether any primary still has an empty backend id.
func SelectorHasRequestSizeConstraints ¶
SelectorHasRequestSizeConstraints reports whether any leaf has min/max context filters.
func ValidateExecutionComposition ¶
func ValidateExecutionComposition( sel *Selector, classes BackendExecutionResolver, policy config.ExecutionCompositionPolicy, ) error
ValidateExecutionComposition checks whether a compiled selector AST conforms to the generation's execution composition policy. Under safe policy:
- A direct primary is always permitted (regardless of backend execution class).
- Composed selectors (weighted, parallel, thinker, failover) require every reachable configured backend to be explicitly classified as inference.
- Reachable backends that are absent from the resolver are ignored here (preserving existing missing-backend authority).
- If classes resolver is nil when evaluating a composite under safe policy, it fails closed.
Under unrestricted policy: - All compositions are allowed.
func ValidateModelAliases ¶
func ValidateModelAliases(rules []ModelAliasRule) error
func ValidateModelAliasesConfig ¶
ValidateModelAliasesConfig compiles model_aliases from cfg (regexp patterns and static replacement selectors). Call after config.LoadFile or equivalent decode; kept out of the config package to avoid a config<->routing import cycle.
func WithNativeModelResolver ¶
func WithNativeModelResolver(ctx context.Context, resolver NativeModelResolver) context.Context
WithNativeModelResolver attaches resolver for request-scoped route planning.
Types ¶
type AffinityMode ¶
type AffinityMode string
AffinityMode controls route-wide backend stickiness. It is intentionally global selector metadata because affinity constrains the whole planning process.
const ( AffinityNone AffinityMode = "" AffinitySession AffinityMode = "session" AffinityClient AffinityMode = "client" )
type AliasResolver ¶
type AliasResolver struct {
// contains filtered or unexported fields
}
func NewAliasResolver ¶
func NewAliasResolver(rules []ModelAliasRule) (*AliasResolver, error)
func (*AliasResolver) Resolve ¶
func (r *AliasResolver) Resolve(s string) string
type AttemptCandidate ¶
type AttemptCandidate struct {
Primary Primary
// Key matches Primary.String() for exclusion maps.
Key string
// MarkedFirst is true when this candidate came from a [first]-annotated weighted branch.
MarkedFirst bool
// IsParallel is true when this candidate belongs to a parallel group (selector '!' arm).
IsParallel bool
// Handicap is the per-leg head-start delay for parallel routing (0 = no handicap).
Handicap time.Duration
// InterleavedRole labels thinker/executor candidates in thinker-aware weighted cycles.
// It is RoleNone for non-thinker weighted selectors.
InterleavedRole interleavedstate.Role
// SelectorKey is the thinker-aware weighted selector key the candidate was planned from.
// Empty for non-thinker weighted selectors.
SelectorKey string
}
AttemptCandidate is one concrete backend:model attempt after parsing and resolution.
func BackendFacingCandidate ¶
func BackendFacingCandidate(c AttemptCandidate) AttemptCandidate
BackendFacingCandidate returns a copy with Primary.Model projected to the bound NativeID for true backend-dependent seams (Open, ResolveCaps, transport caps). Logical Model, Key, affinity, and other identity fields are preserved on the original candidate; only the returned copy's Model is rewritten.
func ExpandFailover ¶
func ExpandFailover(sel *Selector, opt PlanOptions) ([]AttemptCandidate, error)
ExpandFailover resolves a parsed selector into an ordered list of candidates for the first pass: one entry per failover arm (left-to-right), skipping primary arms that are excluded/unhealthy, and resolving each weighted arm with pickWeighted. Arms with no eligible candidates are skipped. When a [first] branch is chosen, Session.FirstRequestConsumed is set (if Session is non-nil).
func InitialCandidates ¶
func InitialCandidates(sel *Selector) []AttemptCandidate
InitialCandidates extracts all possible attempt candidates from a compiled selector AST, preserving exact sequential/fallback, weighted, and race candidate order and membership (Requirements 7.3, 8.3, 8.4, 10.3, 10.4). A nil selector or one with no alternatives returns nil.
func ReplanWeighted ¶
func ReplanWeighted(w *Weighted, opt PlanOptions) (AttemptCandidate, error)
ReplanWeighted picks again within the same weighted group after excluding failed candidates. Req 7.4: retry/failover path ignores [first] and only considers remaining eligible weighted candidates.
type AttemptGroup ¶
type AttemptGroup struct {
Candidates []AttemptCandidate
// NextThinkerCycle is the advanced thinker-aware weighted cycle cursor produced by
// picking a thinker-aware weighted branch. It is nil for non-thinker weighted selectors
// and for primary/parallel arms. Callers persist it when route selection becomes
// authoritative so the next request in the same session continues from the next position.
NextThinkerCycle *interleavedstate.CycleState
}
AttemptGroup is one eligible failover arm after planning. Single-candidate arms (primary/weighted) contain exactly one candidate; parallel arms contain one or more legs.
func ExpandFailoverGroups ¶
func ExpandFailoverGroups(sel *Selector, opt PlanOptions) ([]AttemptGroup, error)
ExpandFailoverGroups resolves a parsed selector into ordered candidate groups (one group per eligible arm). Primary/weighted arms produce one candidate group of length 1; parallel arms produce one group with all eligible parallel legs.
type BackendExecutionResolver ¶
type BackendExecutionResolver interface {
ResolveBackendExecution(backendID string) (class lipsdk.BackendExecutionClass, ok bool)
}
BackendExecutionResolver resolves the execution class of a configured backend instance. If the backend instance is not configured in the active generation, ok is false.
type BackendExecutionResolverFunc ¶
type BackendExecutionResolverFunc func(backendID string) (lipsdk.BackendExecutionClass, bool)
BackendExecutionResolverFunc allows using an ordinary function as a BackendExecutionResolver.
func (BackendExecutionResolverFunc) ResolveBackendExecution ¶
func (f BackendExecutionResolverFunc) ResolveBackendExecution(backendID string) (lipsdk.BackendExecutionClass, bool)
type CandidateAdmissionCheck ¶
type CandidateAdmissionCheck struct {
Call lipapi.Call
Invocation lipapi.Invocation
Candidate AttemptCandidate
BackendCaps lipapi.BackendCaps
TransportCaps lipapi.BackendTransportCaps
ReplaySupport lipapi.ReasoningReplaySupport
DialectSupport lipapi.DialectSupport
ProjectionTarget lipapi.LegacyProjectionTarget
TransportPolicy lipapi.TransportFallbackPolicy
RequireProjection bool
Continuation *ContinuationConstraint
}
CandidateAdmissionCheck evaluates whether one planned candidate can represent the call before upstream work.
func (CandidateAdmissionCheck) Evaluate ¶
func (c CandidateAdmissionCheck) Evaluate() lipapi.CandidateAdmissionResult
Evaluate runs the canonical admission sequence for one candidate.
type ContinuationConstraint ¶
type ContinuationConstraint struct {
Lineage lipcont.Lineage
Requirements lipapi.ProtocolRequirements
NativeRequirements []lipcont.NativeRequirement
}
ContinuationConstraint is the routing projection of stored continuation lineage. Portable records leave BackendID/Model empty and may reroute.
type FailoverAlt ¶
FailoverAlt is one arm of a failover selector (before the next '|'). Exactly one of Primary, Weighted, or Parallel is non-nil.
type GenerationSelectorValidator ¶
type GenerationSelectorValidator struct {
Aliases *AliasResolver
DefaultBackend string
KnownBackends map[string]struct{}
BackendExecutionResolver BackendExecutionResolver
ExecutionCompositionPolicy config.ExecutionCompositionPolicy
}
GenerationSelectorValidator validates route selectors against the current generation's aliases, default backend, known backends, and execution composition policy (Requirements 7, 8). It implements routeoverride.SelectorValidator.
func NewGenerationSelectorValidator ¶
func NewGenerationSelectorValidator( aliases *AliasResolver, defaultBackend string, knownBackends map[string]struct{}, execResolver BackendExecutionResolver, policy config.ExecutionCompositionPolicy, ) *GenerationSelectorValidator
NewGenerationSelectorValidator constructs a GenerationSelectorValidator.
func (*GenerationSelectorValidator) HasRequestSizeConstraints ¶
func (v *GenerationSelectorValidator) HasRequestSizeConstraints(raw string) (bool, error)
HasRequestSizeConstraints reports whether the compiled and validated selector contains any context min/max request-size filters (Requirements 7, 8, 19). A nil validator fails closed and returns an error.
func (*GenerationSelectorValidator) LegalCandidateBackends ¶
func (v *GenerationSelectorValidator) LegalCandidateBackends() []string
LegalCandidateBackends extracts all backend IDs that can legally be selected under this generation's validator. If KnownBackends is nil, returns nil (unbounded/unknown backends). If KnownBackends is non-nil, returns a sorted slice of all known backend IDs.
func (*GenerationSelectorValidator) ValidateSelector ¶
func (v *GenerationSelectorValidator) ValidateSelector(_ context.Context, raw string) error
ValidateSelector compiles raw, verifies all referenced backends are known, and enforces the execution composition policy. A nil validator fails closed: it cannot prove any selector legal.
type ModelAliasRule ¶
ModelAliasRule is one regexp-based rewrite rule for a route selector string.
func ModelAliasRulesFromConfig ¶
func ModelAliasRulesFromConfig(cfg *config.Config) []ModelAliasRule
ModelAliasRulesFromConfig maps decoded config.Config.ModelAliases into ModelAliasRule slices for alias compilation and validation. It returns nil when cfg is nil or has no entries.
type ModelBinding ¶
type ModelBinding struct {
Kind ModelBindingKind
Native string // set for ExactCanonical and KnownNative
}
ModelBinding is the multi-state resolution result for one backend+model leaf.
type ModelBindingKind ¶
type ModelBindingKind int
ModelBindingKind distinguishes request-scoped native resolution outcomes. Exact-backend resolution never selects another backend's row (req 9.10).
const ( // ModelBindingUnspecified is the zero value; treat as unknown pass-through. ModelBindingUnspecified ModelBindingKind = iota // ModelBindingExactCanonical maps (backend, canonical) to that backend's NativeID. ModelBindingExactCanonical // ModelBindingKnownNative means model is already a NativeID published for that backend. ModelBindingKnownNative // ModelBindingUnknown means the raw/native input is unrecognized; preserve as pass-through. ModelBindingUnknown // ModelBindingWrongBackend means the canonical is registered only on another backend. ModelBindingWrongBackend )
type NativeModelResolver ¶
type NativeModelResolver interface {
ResolveModelBinding(backendID, model string) ModelBinding
}
NativeModelResolver maps a route leaf's backend+model using a request-bound registry view. Implementations must be fail-closed across backends.
func NativeModelResolverFromContext ¶
func NativeModelResolverFromContext(ctx context.Context) (NativeModelResolver, bool)
NativeModelResolverFromContext returns the request-bound native resolver when present.
type Parallel ¶
type Parallel struct {
Branches []ParallelBranch
}
Parallel is a set of branches executed concurrently; the first to produce a non-whitespace content delta wins. Branches are separated by '!' in the selector string.
type ParallelBranch ¶
ParallelBranch is one leg of a parallel group.
type PlanOptions ¶
type PlanOptions struct {
Excluded map[string]struct{}
Unhealthy map[string]struct{}
// RequestSize is the current request size estimate used for per-leaf min/max context filters.
// When unavailable, size filters fail open and do not exclude candidates.
RequestSize RequestSizeEstimate
Session *SessionRoutingState
// PreferredCandidateKeys hints expand order when keys are already eligible (design §12, advisory).
PreferredCandidateKeys []string
// StickyBackendID forces a currently bound backend instance ahead of normal weighted/failover selection
// when at least one candidate for that backend is eligible in the current selector.
StickyBackendID string
// Rand supplies weighted-branch rolls. When nil, weighted selection uses a fixed-seeded
// math/rand/v2 PCG stream (deterministic, not crypto-safe); inject for tests or concurrency-safe rolls.
Rand Rng
IsRetryPath bool
// ThinkerCycle is the persisted thinker-aware weighted cycle cursor for the current selector.
// A zero-value (empty) state means no cycle has been established yet; the planner builds a
// fresh cycle from the weighted branches and starts at position 0.
ThinkerCycle interleavedstate.CycleState
// SuppressThinker skips the thinker position during cycle advancement (continuation turns)
// and returns deterministic no-eligible-route outcomes when no executor candidate remains.
SuppressThinker bool
}
PlanOptions configures planning: exclusions, health, session first-request consumption, RNG, retry path.
type Primary ¶
type Primary struct {
// Backend is empty for model-only selectors. It may contain dots (e.g. openai.azure).
Backend string
// Model is the requested/logical identity (canonical or raw pass-through).
// Route keys, affinity, catalog matching, traces, and diagnostics use Model.
Model string
// NativeModel is the request-bound backend wire id when the registry mapped
// this leaf. Empty means unresolved pass-through (use Model at seams).
// NativeModel must not appear in String()/exclusion keys.
NativeModel string
Params url.Values
Size RequestSizeConstraint
TTFTTimeout *time.Duration
}
Primary is a concrete backend:model (or model-only) with optional query parameters.
func (Primary) String ¶
String returns a stable diagnostic key for a primary (exclusion / health maps).
func (Primary) TrimmedParam ¶
TrimmedParam returns the first query parameter value with surrounding whitespace removed.
type RequestSizeConstraint ¶
RequestSizeConstraint carries per-leaf request token eligibility bounds.
type RequestSizeEstimate ¶
RequestSizeEstimate is a provider-neutral request token estimate for route planning.
type Rng ¶
Rng abstracts a uniform integer RNG for weighted picks (see NewSeededRng, WrapRandV2).
func NewSeededRng ¶
NewSeededRng returns a deterministic, non-crypto-strength RNG for weighted routing. The same seed yields the same stream (PCG with a zero second word).
type RoutingScenarioSpec ¶
type RoutingScenarioSpec struct {
ID string
InvariantSummary string
TestName string // exists in internal/core/routing/*_test.go
}
RoutingScenarioSpec links a stable scenario identifier to route-selector and planning invariants and the primary regression test (specification bundle).
func SpecBundleRoutingScenarios ¶
func SpecBundleRoutingScenarios() []RoutingScenarioSpec
SpecBundleRoutingScenarios lists selector, alias, and planner invariants. Keep aligned with .kiro/steering/routing-and-orchestration.md and the referenced tests.
type Selector ¶
type Selector struct {
Alternatives []FailoverAlt
GlobalTTFTTimeout *time.Duration
Affinity AffinityMode
}
Selector is the root AST: an ordered failover chain (left-to-right).
func CompileSelector ¶
func CompileSelector(raw string, aliases *AliasResolver, defaultBackend string) (*Selector, error)
CompileSelector is the shared pure compile path for admin preflight and buildRoutePlan: trim, alias resolution, parse, model-only defaulting, and unresolved-model-only rejection. It must not allocate B-legs, open backends, bind native models, or mutate affinity/weighted-first/interleaved state.
func PrepareSelector ¶
func PrepareSelector( raw string, aliases *AliasResolver, defaultBackend string, classes BackendExecutionResolver, policy config.ExecutionCompositionPolicy, resolver NativeModelResolver, ) (*Selector, error)
PrepareSelector compiles the selector, validates execution composition under the active policy, and binds native model IDs if a resolver is configured. It is the shared pure preparation logic for both canonical route planning (Executor.buildRoutePlan) and wire assessment (ComposeInitialCandidates, InitialRouteAssessmentGate) to eliminate any risk of routing drift (Requirements 7, 8, 19).
type SessionRoutingState ¶
type SessionRoutingState struct {
FirstRequestConsumed bool
}
SessionRoutingState holds session-scoped routing flags (mirrors B2BUA A-leg state; persisted by caller in v1).
type UnsafeExecutionCompositionError ¶
type UnsafeExecutionCompositionError struct {
Composition string
BackendID string
Class lipsdk.BackendExecutionClass
Policy config.ExecutionCompositionPolicy
}
UnsafeExecutionCompositionError records details of an unsafe composition rejection.
func (*UnsafeExecutionCompositionError) Error ¶
func (e *UnsafeExecutionCompositionError) Error() string
func (*UnsafeExecutionCompositionError) Unwrap ¶
func (e *UnsafeExecutionCompositionError) Unwrap() error
type Weighted ¶
type Weighted struct {
Branches []WeightedBranch
}
Weighted is a set of branches; exactly one is chosen per planning step using weights.
type WeightedBranch ¶
type WeightedBranch struct {
Weight int
// IsFirst marks a [first] annotation (only meaningful when not on retry path and session allows).
IsFirst bool
// IsThinker marks a [thinker] annotation; the branch produces a planning memo
// in interleaved-thinking cycles. At most one thinker branch is allowed per
// weighted group, and it cannot combine with [first] on the same branch.
IsThinker bool
// Target is the resolved primary for this branch. Zero when Parallel is set.
Target Primary
// Parallel, when non-nil, marks this branch as targeting an embedded parallel
// executor group. Allowed only on the non-thinker branch of a thinker hybrid
// weighted selector; the parser enforces that narrow shape. Target is zero in
// that case. General weighted/parallel mixing remains rejected.
Parallel *Parallel
}
WeightedBranch is one weighted arm after splitting on '^'.
type WrongBackendCanonicalError ¶
WrongBackendCanonicalError names the rejected leaf for diagnostics.
func (*WrongBackendCanonicalError) Error ¶
func (e *WrongBackendCanonicalError) Error() string
func (*WrongBackendCanonicalError) Unwrap ¶
func (e *WrongBackendCanonicalError) Unwrap() error