# `Statifier.Validator.Context`
[🔗](https://github.com/riddler/statifier-ex/blob/v2.0.0/lib/statifier/validator/context.ex#L1)

The throwaway index the checks share, built once per `Statifier.Validator.validate/2`
call and discarded afterward. It must never be returned, cached, or handed
to the compiler: `Statifier.Compiler` builds the real interned index, and
sharing this one would couple two layers the architecture keeps
independent. Correctness over speed here, per the bead's own design note.

`states` maps a named state's id to its struct. `ancestors` maps a named
state's id to the list of its named ancestors' ids, itself excluded -
`descendant?/3` turns that into a list-membership test rather than a
re-walk. The list carries no order contract: membership is the whole of
what anything reads, and `walk/3` builds it innermost-first to avoid an
append per tree level. A state with a `nil` id cannot be named by anything,
so it is absent from both maps.

`parents` maps **every** state struct (nameless ones included) to its
immediate parent - another `State.t()`, or the `Document.t()` for a
top-level state - which is why it is keyed by the struct itself rather
than by id.

`transitions` is the flat `[{transition, owner}]` list: every
`<transition>` in the document, tagged with the slot it
came from. `owner` is `{:plain, state}` for a state's or parallel's own
transitions, `{:initial, state}` for the transitions inside that state's
`<initial>` element, and `{:history, state}` for a `:history` state's own
transitions (its default-transition candidates). Checks 2, 4, and 5 all
consume this one traversal instead of each re-walking the tree.

`invoke_content_markup?` mirrors `Statifier.compile/2`'s
`invoke_content_markup` option (ADR-0042), defaulting to `false`. It is
not a general validation off-switch: `Statifier.Validator.Checks.Boilerplate`
is the only check that reads it, and only to accept a root that resolves
to no namespace at all, never a root that declares a wrong one.

# `owner`

```elixir
@type owner() ::
  {:plain, Statifier.Document.State.t()}
  | {:initial, Statifier.Document.State.t()}
  | {:history, Statifier.Document.State.t()}
```

# `t`

```elixir
@type t() :: %Statifier.Validator.Context{
  ancestors: %{optional(String.t()) =&gt; [String.t()]},
  invoke_content_markup?: boolean(),
  parents: %{
    required(Statifier.Document.State.t()) =&gt;
      Statifier.Document.State.t() | Statifier.Document.t()
  },
  source: binary(),
  states: %{optional(String.t()) =&gt; Statifier.Document.State.t()},
  transitions: [{Statifier.Document.Transition.t(), owner()}]
}
```

# `build`

```elixir
@spec build(document :: Statifier.Document.t(), source :: binary(), opts :: keyword()) ::
  t()
```

Walks `document` once, threading ancestry as it descends and collecting
the shared transition list. `source` is the binary `document` was parsed
from; it is stored verbatim for checks that need `Location.slice/2`
and is not otherwise read here.

`opts` defaults to `[]`; `invoke_content_markup: true` sets the
same-named boolean field, per `Statifier.Validator.validate/3`.

# `descendant?`

```elixir
@spec descendant?(
  context :: t(),
  ancestor_id :: String.t(),
  descendant_id :: String.t()
) :: boolean()
```

Whether `ancestor_id` is one of `descendant_id`'s named ancestors.

---

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