Modules
This module is the map — what exists and why. Each entry defends a module's
existence; how a module is designed lives in its own @moduledoc.
The MCP mount — the node's entire external surface.
The HTTP entry point: routes paths to YmerNode.Mcp, and answers 404 to
everything else.
The instructions the node hands every MCP client at connect.
The four helpers a tool's action and format layers share, and nothing else.
Wymcp tool notebook — an open SQL surface over notebook.db, the node's own
private store, together with the actions that keep it safe.
Action implementations for the notebook MCP tool
(YmerNode.Mcp.Tools.Notebook, which calls run/2) — a thin boundary over
YmerNode.Notebook and YmerNode.Notebook.Backup. This is a trust boundary:
sql, table and id are guarded is_binary in each head because nothing
downstream validates them — the MCP dispatch layer checks that a parameter is
present but never what type it holds — so sql and table flow straight into
SQLite and id flows into filename construction. Each action returns
{:ok, data, hint_ctx} or {:error, {reason, ctx}} — and, where the error is one
the caller can act on, {:error, {reason, ctx}, hint_ctx}, the three-element form
that puts a follow-up hint on the error payload rather than only in its prose.
Translates YmerNode.Notebook and YmerNode.Notebook.Backup error reasons into
LLM-readable messages. SQLite errors are surfaced verbatim so the agent can read
and fix its own SQL; backup failures never are, because their detail carries
filesystem paths the caller must not see.
Shapes YmerNode.Notebook and YmerNode.Notebook.Backup results into
JSON-serialisable maps for MCP responses.
Query results pass through as parallel columns/rows arrays (compact and
order-preserving) rather than per-row maps.
Follow-up hints for the notebook tool, keyed off the hint_context maps
YmerNode.Mcp.Tools.Notebook.Actions produces. After execute creates schema, the
natural next steps are describing or querying it; after a capture the natural
next step is confirming it. A completed restore needs no follow-up either, since
the roll-back is already done — but a restore that failed recoverably does: the
hint carries the id of the backup to restore, or of the restore to retry, so the
recovery is one call away instead of a re-read of the error text. Everything else
falls through to none — including every answer about a notebook that cannot take
the call, whose next action is a person's and not another tool call, and a
backup that will not open, whose next action is a different id this module has
no way to choose.
Schema definitions for the notebook tool's actions. The :notes/:examples are the
agent's primary documentation for sqlite-vec usage and the INTEGER-PRIMARY-KEY
join discipline — they surface via the help tool.
Wymcp tool references — the registry of pointers at where knowledge lives.
Action implementations for the references tool — the boundary over the
YmerNode.References context.
Translates the references tool's error reasons, optionally with context,
into messages a worker can act on. Called by
YmerNode.Mcp.Tools.References's Wymcp.Tool.handle_error/1.
Response shaping for the references tool.
Follow-up hints for the references tool, keyed off the hint_context maps
YmerNode.Mcp.Tools.References.Actions produces.
Action schemas for the references tool. The notes surface through the
help tool and are the worker-facing contract documentation — the mode
contract, the duplicate rule, and the membrane.
Value validation for the references tool's params.
Wymcp tool script_author — writing the scripts this node accepts.
Action implementations for the script_author tool — the boundary over
YmerNode.Scripts's write verbs.
Translates the script_author tool's error reasons into messages a worker can
act on. Called by YmerNode.Mcp.Tools.ScriptAuthor's
Wymcp.Tool.handle_error/1.
Follow-up hints for the script_author tool, keyed off the hint_context maps
YmerNode.Mcp.Tools.ScriptAuthor.Actions produces.
Action schemas for the script_author tool. The notes surface through the
help tool and are the worker-facing contract of each call — what it does,
what it refuses, what its flags mean. The script contract itself is not
written here: scripts guide renders it from YmerNode.Script's own docs,
and the notes of check and create point there.
Response shaping for both script tools — YmerNode.Mcp.Tools.Scripts and
YmerNode.Mcp.Tools.ScriptAuthor.
Wymcp tool scripts — the scripts this node has accepted, and running one.
Action implementations for the scripts tool — the boundary over
YmerNode.Scripts.
Translates the scripts tool's error reasons into messages a worker can act
on. Called by YmerNode.Mcp.Tools.Scripts's Wymcp.Tool.handle_error/1.
Follow-up hints for the scripts tool, keyed off the hint_context maps
YmerNode.Mcp.Tools.Scripts.Actions produces.
Action schemas for the scripts tool. The notes surface through the help
tool and are the worker-facing contract: what a run costs, what acceptance
means, and why describe is the call to make before run.
The notebook — notebook.db, a separate, portable SQLite store of user- and
LLM-governed memories, working and long-term: agent-defined schema, open SQL,
embeddings, backup and restore. Potentially precious (tutoring records,
curated knowledge); the node's obligation is durability — governance stays with
the user and the LLM. This module is its raw-SQL surface (via
YmerNode.Notebook.Repo).
Capture and restore for notebook.db — the node's one durable obligation.
Singleton mutex serializing YmerNode.Notebook.Backup operations — capture and
restore.
Ecto repo for notebook.db — the node's one deliberate local store.
One-shot boot probe that aborts application start when the sqlite-vec vec0
extension did not load into YmerNode.Notebook.Repo.
The registry of pointers at where knowledge lives, served to LLM workers as
the references tool; it holds references, never copies of what they point at
(the membrane).
One row of the registry: a pointer naming where knowledge lives and when to
look, never what it says. The rule that keeps it a pointer — the membrane —
is stated in YmerNode.References.
The find surface — two composable layers on one call.
Derives a reference's source and fetch recipe from its uri, at read time and never from storage.
Ecto repo for node.db — the node database, and the rebuildable half of what
the node stores.
The contract a script implements — its description, its actions and their
read/write marks, its declarations — and the version use YmerNode.Script
stamps into its row.
What the node hands every run — Req, JSON, the notebook, secrets, the
throttles it declares, the node's time zone, the files directory and the
Typst renders — provided by the node rather than declared by the script.
The scripts this node has accepted, and every door they arrive and leave through — the context both script tools wrap and the node's own callers use.
The operator's verbs, run on the machine the node runs on — the node's own human door, beside the client's approval.
Turns a script's code into a loaded module tree, or into a refusal that names what is wrong with it.
The text scripts guide renders — the script contract and the batteries a
script is handed — read at the call from the docs the release keeps.
Owns the VM's script module trees: every compile and every purge goes through this process, and it remembers what each one produced.
A promised package's own documentation, rendered from this release — what
scripts info <name> answers.
One run of one action — what is checked before it, the process it happens in, and the shape of every answer that comes back.
An Elixir module stored as a row in the node database — its code, the hash of
that code and the hash this node has accepted — compiled into the VM and
reachable through the scripts tool and by the node itself; Script.<Name>,
named after its module.
One throttle on this node: the process that holds its bucket, its breaker and the requests waiting on it — and the two request steps that put a request naming it through that process.
A throttle's token bucket as a value: a rate per minute, a burst, the tokens it holds and the instant it last counted them.
A throttle's refusal of a request — the exception YmerNode.Script.Context.request/2
answers as {:error, exception} when a request never left the node.
The values a script resolves by name — one file of NAME=value lines,
outside every database.
Mix Tasks
Build the release image and tag it with the commit it was built from.
A subprocess's output reaching the terminal as it is produced — faithful
for valid UTF-8, with anything unreadable shown as �, and unable to stop
the task that runs it, whatever bytes it carries.
Deploy: move the checkout's committed main into the install — name the
rollback target, build, carry the compose file, recreate the install's
container on the image, and verify it came up on it.