Dogfood: describe the publish manifest record type using MLF itself.
lexicons/lol/mlf/package.mlf defines a record package with a
self {} doc block carrying the lexicon-level description, plus two
supporting object types (PublishedItem and ResolvedDependency) that
keep the record's array shapes readable.
Repo-root mlf.toml declares [package].name = "lol.mlf", points [source] at ./lexicons, and configures a single [[output]] for rust writing to ./mlf-generated-lexicon/src/generated. We deliberately don't emit lexicon JSON to the repo — the publish flow produces that shape when it actually ships records to a PDS; keeping a static copy would just be a stale duplicate.
Generated code lives in its own workspace crate, mlf-generated-lexicon. Its src/lib.rs stitches each generated file under a module path that mirrors the lexicon NSID (so lol.mlf.package shows up as mlf_generated_lexicon::lol::mlf::package). Crates that want typed access depend on it like any other workspace member — no build-script magic, no include! from "up here".
mlf-publish::manifest imports Package / PublishedItem /
ResolvedDependency from the new crate and builds the instance payload
via serde instead of hand-rolled JSON macros. Any drift between the
.mlf schema and the code that builds manifests now surfaces at
compile time. The com.atproto.lexicon.schema envelope fields
($type, lexicon, id, description, defs) stay hand-assembled: the
atproto meta-schema only requires lexicon: integer, so there's
nothing useful to generate a type from, and the envelope shape is
guarded by the check_meta_schema validator.