# `Mnemosyne.Graph`
[🔗](https://github.com/edlontech/mnemosyne/blob/main/lib/mnemosyne/graph.ex#L1)

Core knowledge graph data structure.

Stores nodes indexed by ID, type, tag label, and subgoal description.
Supports bidirectional linking between nodes and batch mutation via changesets.

# `t`

```elixir
@type t() :: %Mnemosyne.Graph{
  by_subgoal: %{required(String.t()) =&gt; MapSet.t()},
  by_tag: %{required(String.t()) =&gt; MapSet.t()},
  by_type: %{required(atom()) =&gt; MapSet.t()},
  nodes: %{required(String.t()) =&gt; struct()}
}
```

# `apply_changeset`

```elixir
@spec apply_changeset(t(), Mnemosyne.Graph.Changeset.t()) :: t()
```

Applies a changeset's additions and links to the graph.

# `delete_node`

```elixir
@spec delete_node(t(), String.t()) :: t()
```

Removes a node from the graph, cleans up link references, and rebuilds indexes.

# `get_node`

```elixir
@spec get_node(t(), String.t()) :: struct() | nil
```

Fetches a node by its ID, returning `nil` if not found.

# `link`

```elixir
@spec link(t(), String.t(), String.t(), Mnemosyne.Graph.Edge.edge_type()) :: t()
```

Creates a typed bidirectional link between two nodes. No-op if either ID is missing.

# `new`

```elixir
@spec new() :: t()
```

Creates an empty graph.

# `nodes_by_type`

```elixir
@spec nodes_by_type(t(), atom()) :: [struct()]
```

Returns all nodes matching the given type atom.

# `put_node`

```elixir
@spec put_node(
  t(),
  struct()
) :: t()
```

Inserts a node into the graph, updating all secondary indexes.

---

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