The parsed result of a routing call (Mimir.RouterClient.route/2). This is
the single boundary where an atom- or string-keyed decoded JSON response is
turned into mimir's struct vocabulary: build with new/1, then consume
assertively (resp.grant.budget_microdollars, pattern-match on verdict).
Downstream code never touches a raw route map.
new/1 unifies the wire's two locations for reasons/candidates — nested
inside placement on a placement verdict, top-level on a no_candidate
verdict — onto the top-level reasons/candidates fields, so consumers see
one shape regardless of verdict.
Summary
Types
@type t() :: %Mimir.RouteResponse{ candidates: [Mimir.Candidate.t()], decision_id: String.t() | nil, grant: Mimir.Grant.t() | nil, placement: Mimir.Placement.t() | nil, reasons: [String.t()], snapshot_at: String.t() | nil, step_id: String.t() | nil, verdict: :placement | :no_candidate, workflow_id: String.t() | nil }