# `StatifierBlocks.Compiler.Attribution`
[🔗](https://github.com/riddler/statifier_blocks/blob/v0.44.1/lib/statifier_blocks/compiler/attribution.ex#L1)

Resolves each element of one block's emission to the block an author
would recognise (ADR-0004 decision 5).

The compiler calls `stamp/2` on a block's own emission the moment
`emit/2` returns it, **before** the children are spliced in. So each
block stamps only what it wrote, every element ends up owned, and the
spliced tree is total by construction rather than by a later sweep that
would have to guess.

## The three rules

  * **Default.** An element belongs to the block that emitted it, with
    no config key.
  * **Role.** An element whose `id` is a state id this block minted
    (`StatifierBlocks.Compiler.StateId.unstate_id/1`) takes that role,
    and everything inside it inherits the role until another state
    changes it. That is what puts `s_blk_AUTH__running`'s `<invoke>` on
    `blk_AUTH` role `running` rather than on the block as a whole.
  * **Override.** `StatifierBlocks.Emission.attributed_to/2` moves an
    element and its subtree to another block and clears the role, which
    is the case decision 5 names: "attribution is a judgment, not a
    mechanism". `StatifierBlocks.Emission.from_config/2` and
    `attribute_from_config/3` set the config key that makes a finding
    the author's.

## An attribution has to name a block in this document

A block type may only attribute an element to a block the compiler
actually knows about - in practice, one of its own children, which is
the only case decision 5 raises. `stamp/2` takes the set of block ids
that are legitimate targets and refuses anything else, because an owner
naming a block the document does not contain is an unresolvable entry in
a map whose whole purpose is resolving.

# `stamp`

```elixir
@spec stamp(
  StatifierBlocks.Emission.t(),
  StatifierBlocks.Block.id(),
  MapSet.t(StatifierBlocks.Block.id())
) ::
  {:ok, StatifierBlocks.Emission.t()}
  | {:error, {:unknown_attribution, StatifierBlocks.Block.id()}}
```

Stamps a resolved owner onto every element of `emission`.

`known` is the set of block ids `Emission.attributed_to/2` may name -
the emitting block and its compiled children. Descends into elements
only; a `{:child, _}` placeholder is left alone, because the child
stamped its own subtree when it was compiled.

---

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