Action implementations for the references tool — the boundary over the
YmerNode.References context.
This is a trust boundary. Its shape check is on the heads — every run/2
clause guards is_map(data), because it binds the params map whole, and each
private head pattern-matches the keys the schema declares required. Its
value checks sit one layer down: YmerNode.Mcp.Tools.References.Validate
type-checks every scalar a find or an id-bearing action extracts, and the
YmerNode.References.Reference changeset does the same for every field add
and update write, so no value reaches anything type-assuming before one of
those two has judged it. The notebook tool guards its extracted scalars on the
heads as well, because its values flow straight into SQLite and into filename
construction with nothing in between; that is not this tool's shape.
One read of the seam per action, threaded down.
YmerNode.References.Sources.declarations/0 is a database query, and every
action that needs it reads it once at the top and passes it on — to
YmerNode.Mcp.Tools.References.Validate for the source vocabulary, to
YmerNode.References for the filter, and into the error context so an
invalid-source message names the same vocabulary the call was judged against.
Nothing below this layer reaches back for a fresh read, and
YmerNode.Mcp.Tools.References.Format cannot classify at all — it takes the
answer. A find returning fifty references costs one read and fifty
classifications, which is the floor.
add's duplicate branch is deliberately a SUCCESS response. An LLM reads an error as "retry differently", which would fork the registry through a slightly mutated uri; pointing at the reference that already exists, with an update-or-tag steer, converges instead.