# `StatifierBlocks.Runtime.Subchart.Resolution`
[🔗](https://github.com/riddler/statifier_blocks/blob/v0.44.1/lib/statifier_blocks/runtime/subchart/resolution.ex#L1)

The half of the `statifier_blocks:subchart` handler that is pure in both
variants: turning the document id on `src` into a compiled child chart,
or into one of the three shared refusal reasons.

ADR-0008 decision 2 says the resolver contract is the durable module's
too, "in full and without additions", and that resolution is therefore
"shared code, not a second copy". This module is that shared code.
`StatifierBlocks.Runtime.Subchart` (in-memory, `Statifier.Session`) and
`StatifierBlocks.Runtime.DurableSubchart` (durable,
`StatifierPersistence.Driver`'s dispatch fun) both call `resolve/3` and
differ only in what they do with its two answers - which is exactly the
"what differs between the variants begins after resolution has produced
a chart" line the record draws.

The resolver contract itself, the behaviour, and every word of
documentation about it stay on `StatifierBlocks.Runtime.Subchart`: this
module mints nothing and is not part of the package's public surface.

## `:known_invoke_types` is passed only when the ctx can supply it

The in-memory ctx is a `t:Statifier.Invoke.Handler.ctx/0` and carries
`:invoke_handlers`, the set the runtime will classify against, so a
child compile gets ADR-0004 decision 8's opt-in lint. A durable
dispatch context carries no such key - the durable seam's registry is
the host's dispatch fun, not a handler map - so the option is
**omitted** rather than passed as an empty set. Omitted, the compiler
does not run the lint at all (`StatifierBlocks.Compiler`'s
`Keyword.fetch/2`). Passed empty, it would run and report every invoke
type in the child as unregistered - starting with
`statifier_blocks:subchart` itself in a nested durable subchart
(ADR-0008 decision 6) - which is a false claim about the host's
registration rather than a true one. The lint is warning-only
(`StatifierBlocks.Compiler.InvokeTypes`), so neither choice can change
a refusal; the choice is between silence and noise, and silence is the
honest one where there is nothing to compare against.

# `reason`

```elixir
@type reason() :: String.t()
```

The reason a start refused, always one of the closed refusal set.

# `t`

```elixir
@type t() :: {:ok, String.t()} | {:refuse, reason(), map()}
```

A resolved child chart's SCXML, or a refusal carrying its reason and JSON-shaped detail.

# `resolve`

```elixir
@spec resolve(Statifier.Effect.Invoke.t(), map(), module()) :: t()
```

Resolves `invoke`'s `src` through `host.resolve_chart/2` and compiles
the result for child use, or refuses.

`ctx` is handed to `resolve_chart/2` unchanged - a
`t:Statifier.Invoke.Handler.ctx/0` in the in-memory case, a
`StatifierPersistence.Driver` dispatch context in the durable one.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
