Repair the graph: retype a mislabelled edge, turn a backwards one around, or
remove one that should not exist. The counterpart to ``memory_relate`` — without
it, an edge written in haste is permanent, and every wrong edge keeps competing
for one of the 3 spreading-activation slots on its memories forever.
**Retype** by passing ``new_relation_type`` alongside ``relation_type``. The
edge is relabelled in place: direction, creation time and metadata survive,
because the usual repair is "right connection, wrong label" and the graph
should keep an honest record of when the link was first drawn. If an edge of
the new type already joins the pair, the two collapse into one and the
outcome reports ``merged`` rather than ``retyped`` — the edge count drops by
one, and nothing is fabricated to hide that.
**Reverse** by passing ``reverse=True`` alongside ``relation_type``. The
endpoints are swapped on the same row, so id, creation time and metadata
survive exactly as they do for a retype — the connection was right, only the
arrow pointed the wrong way. Reversing COMBINES with ``new_relation_type``, in
one write, because an edge recorded backwards is often mislabelled as well.
Note that reversing ``parent_of``/``child_of`` is the same operation as flipping
between the two types: do one or the other, not both. As with a retype, an
existing edge in the target direction absorbs this one and reports ``merged``.
**Delete** by omitting ``new_relation_type`` and ``reverse``. With ``relation_type``, only
that edge goes; without it, every edge from ``source_id`` to ``target_id``
goes, whatever the type. Deletion here is not the bulk prune the graph
guidance warns against: the caller names each edge, exactly as
``memory_forget`` names a memory.
**Batch** by passing ``edges`` — an array of up to 100 objects, each with
``source_id``, ``target_id`` and optionally ``relation_type`` /
``new_relation_type`` / ``reverse``, i.e. the same decision made once per edge:
[{"source_id": "a", "target_id": "b",
"relation_type": "related_to", "new_relation_type": "caused_by"},
{"source_id": "c", "target_id": "d",
"relation_type": "caused_by", "reverse": true},
{"source_id": "e", "target_id": "f", "relation_type": "related_to"}]
A batch is reviewed decisions submitted together, NOT a criteria-driven
sweep, and that is deliberate. There is no "retype every ``related_to`` in
this namespace" option, because the whole point of retyping is that each edge
deserves a different type based on what it actually records — a blanket
relabel would manufacture directional claims that were never true, and a
false ``caused_by`` is worse than an honest ``related_to``.
The batch is validated in full before anything is written, so a malformed op
fails the whole call rather than leaving the graph half-repaired. Individual
outcomes (``retyped``, ``reversed``, ``merged``, ``deleted``, ``not_found``,
``unchanged``) are reported per edge. Use ``dry_run=True`` to preview a sweep
first; nothing is written and each op reports what it would have done.
Find the edges to repair with ``memory_edges``.