# `Minga.Extension.ContributionCleanup`
[🔗](https://github.com/jsmestad/minga/blob/main/lib/minga/extension/contribution_cleanup.ex#L1)

Source-owned contribution cleanup coordinator.

The extension supervisor lives in the core `Minga.*` layer, so it cannot depend on editor presentation modules directly. Editor-layer registries register cleanup callbacks here when they accept source-owned contributions. The supervisor calls this module with a source, and the coordinator cleans core registries plus any registered higher-layer callbacks without creating compile-time upward dependencies.

# `cleanup_failure`

```elixir
@type cleanup_failure() :: %{
  family: atom(),
  source: contribution_source(),
  reason: term()
}
```

Cleanup failure reported for one family.

# `cleanup_fun`

```elixir
@type cleanup_fun() :: (contribution_source() -&gt; :ok | {:error, term()})
```

Cleanup callback invoked with a source identifier.

# `cleanup_opts`

```elixir
@type cleanup_opts() :: [
  command_registry: GenServer.server(),
  keymap: GenServer.server(),
  callbacks: %{required(atom()) =&gt; cleanup_fun()}
]
```

Cleanup options with injectable test registries.

# `contribution_source`

```elixir
@type contribution_source() ::
  :builtin | :config | {:bundle, atom()} | {:extension, atom()}
```

Source that contributed registry entries.

# `register`

```elixir
@spec register(atom(), cleanup_fun()) :: :ok
```

Registers a cleanup callback for a contribution family.

# `unregister`

```elixir
@spec unregister(atom()) :: :ok
```

Unregisters a cleanup callback. Mostly useful for tests.

# `unregister_source`

```elixir
@spec unregister_source(contribution_source(), cleanup_opts()) ::
  :ok | {:error, [cleanup_failure()]}
```

Removes all contributions owned by a source.

---

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