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.
A wrong-typed value used to match no head at all and crash into the framework's
top-level rescue, which told the caller only that a function clause did not
match. Each guarded head now has an unguarded twin at the bottom of the module
that answers {:wrong_type, …} instead, naming the key, the type wanted and
what arrived. The guard is still what keeps the bad value out of SQLite and out
of filename construction; the twin only makes the refusal readable.