Mova Eel
Eel is Mova's learner (Rust on Mova), supervised by Crab; the Octopus — a large language model (LLM) — develops it. See the sea animals of Mova.
Reusable cooperative idle-GPU continuation through Mova's native parser. This crate owns the working controller and trainer: independent GPU leases, immutable annotation export, actual treeagree invocation, native gparse baseline/train/ reload, finite CUDA evidence, developer gates, conditional weight installation, crash reservations, durable receipts and bounded artifact retention. It has no private-source dependency. It does not launch a teacher or another AI provider.
Eel trains only the native syntax (AST) model, gparse. Training of the pragmatics model is not implemented in this crate.
A deployment implements TrainingData::status and TrainingData::export and
calls mova_eel::run(&configuration, once, &mut data). Ordinary foreground
training uses mova_eel::trainer::run. Status is a polling hint; a concurrent
annotation writer may advance the generation before the immutable export. The
export's SHA-256 identity owns the reservation. Both identities are validated
before use in generation paths. Export supplies train_path, dev_path,
agreed_input_train_path, parsers_dir, missing_training_witness_ids and
generation_sha256 using the existing versioned snapshot contract. Missing real
parser witnesses stay excluded; the engine cannot manufacture them.
The configuration injects absolute native gparse, treeagree, model_dir,
run_root, shared gpu_lock, pinned developer/protected data and runtime limits.
The native executable must be gparse itself, not a wrapper taking the same GPU
lock. controller_executable rejects an additional wrapper by path/content.
The legacy peta_executable alias, owner identifiers and installer lock filenames
remain accepted or retained to cooperate with older controllers during upgrades.
Those are compatibility protocol identifiers, never deployment paths or data.
Fresh training admits only ids with a school: prefix by default. A deployment that admits another kind of
reviewed annotation names it: fresh_train_prefixes (each a lowercase name and :, for example ["hard:"] for the
hard-case lane of tools/hard-cases). Every other gate is unchanged; an id outside the named prefixes still fails
the round as nonteaching.
The idle policy remains one epoch, learning rate 0.00003, sampling 0.15 by default (admissible 0.01..0.25), a new checked seed, bounded child deadlines, an explicit fixed LAS floor and cooperative cooldown. A sample fraction is a work budget, not an output-error percentage. Probe-idle does not guarantee the next trainer lease. Deferred rounds preserve rejection streaks and may advance the counter without training. Three rejections increase cooldown; they do not establish a new rejection on each deferred round.
evidence::inspect accepts historical trainer/Eel receipts and separates
deferred, below_threshold, rejected, and installed. Recorded candidate or
installation evidence needs actual-parent/generation/output digest fields;
proposed-parent hashes cannot replace actual-parent lineage. Partial historical
receipts remain incomplete. This classifies declared local evidence, not artifact
authenticity, successful generalization or current deployed-weight identity.
New Eel summaries add this interpretation without changing existing fields.
Tests use finite synthetic CoNLL-U and fake native executables to exercise real Rust callpaths, command arguments, locks, gates and installation. They perform no operational training, teacher calls or protected-label assessment. A public crate build and private adapter build are separate from deployment: an existing running binary continues its previous implementation until explicitly replaced at a verified quiescent boundary. See the source-bound groupants for limitations.
Optional urgent reviewed diagnostics use TrainingData::priority. Reviewed
bypasses ordinary polling/export and consumes a deployment-verified immutable
snapshot; AwaitingReview yields without ordinary training. An untrusted failure
queue must not be mapped blindly to AwaitingReview: only an operator-admitted
active urgent case may block ordinary work. Ambiguity can require root/consultant
review first. Backends rank deterministically and implement durable/idempotent
priority_terminal; the default acknowledgement refuses rather than silently
forgetting terminal work. Failed acknowledgement preserves the terminal native
receipt, and same-run retry cannot repeat compute. Eel propagates uncertainty and
pauses. Installation, queue acknowledgement and Eel summary are separate commits;
manual reconciliation may be required after a crash between them.
A matching data generation alone cannot acknowledge urgent work: the terminal
receipt must also carry the selected diagnostic identity. Historical ordinary
receipts therefore remain ordinary even if their data generation matches.
Autoencoder rounds
With eel_autoencoder in the configuration, the Eel alternates its parser rounds with autoencoder
rounds: round n is an autoencoder round when n mod every = every − 1 (every = 2 alternates).
The kind is chosen at the round boundary; a round of either kind runs to its end, so a parser round is
never interrupted and a switch of configuration happens between rounds (STOP, then a restart with
the new configuration and a new run root). An autoencoder round runs on CPU and never takes the GPU
lease; while it runs the GPU is free for other work, and the next parser round probes the GPU as
before.
An autoencoder round runs the pinned native roundtrip wiki-round (tools/roundtrip, wiki.rs):
a fixed dev sample and a fixed test sample of Wikipedia articles (split by article title, never
trained on), the k-th fresh train window, the residual bits of the exact round trip on dev and test
with the tables in use and with a candidate (en's order generator adapted on the installed domain
and the window). The Eel checks the files itself — sizes, no train article among the dev or test
articles, dev and test equal to the pin written by the first round, the measured tables are the
installed ones — and installs only when the dev bits go down and every dev volume comes back byte
for byte: the candidate is copied to state_dir/gen-<round>/ and state_dir/current (a symlink)
switches to it in one rename, the previous generation stays beside it (three are kept). A refused
candidate leaves the tables as they are and is a terminal rejected receipt
(autoencoder_dev_bits_gate, autoencoder_exact_gate); a failed check pauses the Eel. The test
bits are recorded and decide nothing. The parser rejection streak is not changed by autoencoder
rounds.
key of eel_autoencoder | meaning |
|---|---|
every | the schedule, 2..1000 |
roundtrip, roundtrip_sha256 | the native executable, pinned |
base_model, base_model_sha256 | en.bin, pinned; the parent before the first install |
corpus | the Wikipedia corpus root (tier-1 shards) |
state_dir | the installed tables, dev.json, generations; outside run_root |
shards, train_sentences, dev_sentences, per_article, domain_max | the sample and the domain cap |
threads, nice, timeout_seconds | the child's CPU share and deadline |
The tables and the samples are learned from Wikipedia text (CC BY-SA 4.0): they stay in the data store, never in git or a release.
The turn schedule and the other round kinds
With eel_schedule the Eel takes turns among round kinds; without it, the schedule above holds. eel_schedule.cycle
is either a list of kinds, taken as written and repeated, or an object of weights, expanded once by the smooth
weighted round robin (each turn every kind gains its weight; the kind with the most credit runs and pays the total;
ties go in the order of schedule::KINDS). Round n is turn n mod L; its ordinal among rounds of its kind (the k-th
French parser round, the k-th autoencoder window) counts the earlier rounds of that kind. The kind is chosen at the
round boundary, as before: a round of any kind runs to its end.
| kind | work | configuration | GPU |
|---|---|---|---|
parser | the English parser round | top-level keys | lease |
ae | the English autoencoder round | eel_autoencoder | no |
ae-fr | the French autoencoder round (the same code) | eel_autoencoder_fr | no |
parser-fr, prag-fr, cross, tr-en-fr, tr-fr-en | a gated native round | eel_native.<kind> | no |
An autoencoder section may carry its condition: {"language": "fr", "dialect": null | "CA" | …, "style": null | "encyclopedic" | "official" | "house:<publication>" | …}. A dialect and a style are deltas over the language's
standard; the tables of one state directory belong to one condition, pinned in its dev.json (an English section
without a condition keeps its earlier pin). Every kind needs its own state_dir.
A gated native round (native.rs) runs a pinned executable with pinned arguments, --round k --out <round>/out --threads t [--current <state>/current] [--base <base>], and checks the files itself: the report's metric is the
configured one, the measured parent is the installed generation (or the base), the dev sample's hash equals the pin
of the first round, no train key is a dev or test key. Gate install: the candidate's files are installed as a new
generation (gen-<round>, current switched by one rename, three kept) when the dev metric improves by more than
min_gain; otherwise a terminal rejected receipt (<kind>_dev_gate). Gate measure: a measurement round, outcome
measured, nothing installed; with control, the round's own negative control must look worse than the real value
by ratio in the control metric's direction, or the receipt is rejected (<kind>_control_gate) and nothing is
queued. Proposals (out/proposals.jsonl) go to state_dir/proposals/round-<n>.jsonl, each marked proposed,
review-only: the Eel never admits them as gold. A native round never changes the English parser's rejection streak.
The executables of these kinds are peta/tools/eelfr (internal: it reads Wikipedia).
examples/cpu_rounds.rs drives a schedule without English parser rounds, for measurements outside a deployment;
examples/plan.rs validates a configuration and prints its planned turns without starting anything.
Build and test
A standalone workspace (own Cargo.lock), not built by the root cargo build:
cargo build --release --manifest-path tools/eel/Cargo.toml
cargo test --release --manifest-path tools/eel/Cargo.toml
This crate is a library (mova_eel); a deployment links it and calls mova_eel::run as described above.
Sources
Library ids are folders of the paper library (docs/usage.tsv lists the works outside it).
- Autoencoder rounds kept by held-out description length: grunwald-2007 (MDL), hinton-1993 (autoencoders and MDL), hinton-2006 (autoencoder compression); see also roundtrip — where each layer of Mova loses information.
- The smooth weighted round robin of the turn schedule: the interleaving used by nginx's upstream balancer; no paper.
- The control gate of a measurement round follows the project rule that a gate must be able to show red.
This page in Markdown → https://md.mova.elamur.ai/free/en/docs/tools/eel/