# Lane Selection Guide
`ASM` separates lane discovery from execution mode. Provider resolution decides
which backend lane is preferred, and only then does execution mode decide
whether that lane can actually run.
## The Three Lane Values
- `requested_lane`: what the caller asked for (`:auto | :core | :sdk`)
- `preferred_lane`: what provider/runtime discovery selected before execution-mode checks
- `lane`: the backend lane that actually executed
This distinction matters most when `execution_mode: :remote_node` is involved.
## Lane Policies
- `:core` always resolves to `ASM.ProviderBackend.Core`
- `:sdk` resolves to `ASM.ProviderBackend.SDK` only when the provider runtime kit is installed locally
- `:auto` prefers `:sdk` when that runtime kit is available locally, otherwise it uses `:core`
Use `ASM.ProviderRegistry.provider_info/1` when you want provider-level facts,
`lane_info/2` when you want discovery without execution-mode compatibility, and
`resolve/2` when you need the effective backend choice for a real run.
## Local Versus Remote Execution
Lane selection remains discovery-driven in both modes:
- local runs can execute either `:core` or `:sdk`
- local `:core` and local `:sdk` preserve the same normalized
`execution_surface` contract
- remote runs execute only the core lane in the landed Phase 3 boundary
- `lane: :sdk` with `execution_mode: :remote_node` is a configuration error
- `lane: :auto` may still report `preferred_lane: :sdk` but execute with `lane: :core`
Typical remote auto-lane resolution:
```elixir
{:ok, resolution} =
ASM.ProviderRegistry.resolve(:codex,
lane: :auto,
execution_mode: :remote_node
)
resolution.observability
# %{
# requested_lane: :auto,
# preferred_lane: :sdk,
# lane: :core,
# backend: ASM.ProviderBackend.Core,
# execution_mode: :remote_node,
# lane_fallback_reason: :sdk_remote_unsupported,
# ...
# }
```
## Observability Fields
Lane resolution is projected into both streamed `%ASM.Event{}` metadata and the
final `%ASM.Result.metadata` map.
Common fields:
- `requested_lane`
- `preferred_lane`
- `lane`
- `backend`
- `execution_mode`
- `lane_reason`
- `lane_fallback_reason`
- `sdk_runtime`
- `sdk_available?`
- `capabilities`
That shared metadata keeps stream consumers and one-shot query consumers in
sync about which runtime path actually executed.