Spectre.Router.Support (Spectre v0.3.0)

Copy Markdown View Source

Shared router normalization and logging helpers.

Router plugs should stay small and focused on one evidence source. This module holds the common boundary work: filtering visible rules, converting adapter maps into %Spectre.Route{} structs, formatting fallback reasons, and keeping log output consistent across strategies.

Summary

Functions

Builds the trace reason used when scoped labels are ambiguous.

Returns labels that a label-only provider cannot resolve to one visible rule.

Builds a degraded fallback route from local classifier metadata.

Builds the degraded route for a failed probabilistic strategy.

Formats fallback reasons for logs.

Returns unique labels for a rule set in evaluation order.

Logs router messages when classification logging is enabled.

Logs route score summaries.

Normalizes adapter classifier/cache output into a Spectre route.

Builds an accepted route from a rule and strategy.

Returns rules visible to a router strategy.

Summarizes local classifier state for logs.

Applies terminal routing metadata.

Adds labels to a route-like map.

Functions

ambiguity_reason(strategy, labels)

@spec ambiguity_reason(atom(), [atom()]) ::
  {:ambiguous_scoped_labels, atom(), [atom()]} | nil

Builds the trace reason used when scoped labels are ambiguous.

ambiguous_labels(rules, strategy, input \\ nil)

@spec ambiguous_labels([Spectre.Rule.t()], atom(), Spectre.Input.t() | nil) :: [
  atom()
]

Returns labels that a label-only provider cannot resolve to one visible rule.

Deterministic providers can retain duplicate labels because their evidence identifies a concrete rule. Classifiers, semantic caches, and LLM classifiers return only a label, so duplicates are ambiguous even when their mounted scopes differ.

fallback_route(labels, local_result, reason)

@spec fallback_route([atom()], map(), term()) :: Spectre.Route.t()

Builds a degraded fallback route from local classifier metadata.

fallback_route(rules, input, labels, local_result, reason)

@spec fallback_route(
  [Spectre.Rule.t()],
  Spectre.Input.t() | nil,
  [atom()],
  map(),
  term()
) ::
  Spectre.Route.t()

Builds the degraded route for a failed probabilistic strategy.

Recovery order: a confident local classifier result first, then the agent's declared :UNKNOWN rule (when it has a handler whose checks match the input) so the agent's explicit fallback behavior runs instead of an empty reply, and only then the bare :unknown route. Failure metadata (local, fallback_error) is preserved on the recovered route.

format_reason(reason)

@spec format_reason(term()) :: String.t()

Formats fallback reasons for logs.

labels_for(rules)

@spec labels_for([Spectre.Rule.t()]) :: [atom()]

Returns unique labels for a rule set in evaluation order.

log(level, message, opts)

@spec log(atom(), String.t(), keyword()) :: :ok

Logs router messages when classification logging is enabled.

log_route(level, stage, route, opts)

@spec log_route(atom(), String.t(), map(), keyword()) :: :ok

Logs route score summaries.

route_from_result(route, rules, labels, strategy)

@spec route_from_result(
  map() | Spectre.Route.t(),
  [Spectre.Rule.t()],
  [atom()],
  atom()
) ::
  Spectre.Route.t()

Normalizes adapter classifier/cache output into a Spectre route.

route_from_rule(rule, strategy, raw, labels)

@spec route_from_rule(Spectre.Rule.t(), atom(), String.t(), [atom()]) ::
  Spectre.Route.t()

Builds an accepted route from a rule and strategy.

rules_for(rules, strategy, input \\ nil)

@spec rules_for([Spectre.Rule.t()], atom(), Spectre.Input.t() | nil) :: [
  Spectre.Rule.t()
]

Returns rules visible to a router strategy.

A rule with no explicit via: remains visible to every strategy. When a rule declares via: [:classifier], deterministic regex and LLM fallback plugs will ignore it.

summarize_local(other)

@spec summarize_local(term()) :: String.t()

Summarizes local classifier state for logs.

terminalize(route, opts)

@spec terminalize(
  map(),
  keyword()
) :: Spectre.Route.t()

Applies terminal routing metadata.

with_labels(result, labels)

@spec with_labels(map(), [atom()]) :: Spectre.Route.t()

Adds labels to a route-like map.