Elamur GroupantsβŒ•
☰

roundtrip-wiki-rounds

The groupant beside tools/roundtrip/src/wiki.rs in the Mova repository: what the code computes, what it never does, how to go back from its outputs, its invariants, cost and checks.

Facts

Implementation material. A Mova code model describes this code at one source revision: partial models, finite checks and their stated scope. It is not a reviewed general exposition, and its labels are shown as written, never raised.

Components

componentlabelwhere
Approximantpartial source derivedForward
Astpartialsyntax.json
Compositionpartial source derivedComposition
Costpartial source derivedInvariant and cost
Descriptantpartial source derivedDescriptant
Invariantpartial source derivedInvariant and cost
Testsfinite evidenceTests

Obernants

The typed relations around the forward model: the behaviour complement (what the code never does), the reverse reconstruction (every input compatible with an output) and specialised views.

relationtypelabelwhere
Behavior complementbehavior complementpartial source derived finite checksBehavior complement
Reverse reconstructionreverse reconstructionpartial source derived finite checksReverse reconstruction

Model text

Descriptant

roundtrip wiki-round: one autoencoder learning round on Wikipedia text. It draws a deterministic sample from the tier-1 records of Mova's Wikipedia corpus (a fixed dev sample, a fixed test sample and the k-th fresh train window), measures the exact round trip's residual bits on dev and test with the tables in use, adapts en's order generator on the installed domain plus the window, measures again and writes round.json. It decides nothing: the Eel gates and installs. Its outputs hold Wikipedia text (CC BY-SA 4.0) and stay outside git and releases.

Forward

Pool P = articles of shards 0..S in shard order. h(t) = fnv("ae-dev\0" + t): dev if h mod 20 = 0, test if h mod 20 = 1, train otherwise. Dev and test: their articles ordered by their own keys, the first per_article sentences each, until dev sentences (the last article cut). Train: articles ordered by fnv("ae-train\0" + t); window k starts at article (k·⌈train/per_articleβŒ‰) mod |train|, epoch = the quotient, and takes articles cyclically until train sentences. Volumes: one per article, one sentence a line. Measure: pipeline::run exact, unit block, merged in volume order; bits = sum of every residual cell. Candidate: domain = last domain_max lines of (installed domain ++ window), Model::adapt(domain, 1) (linearizer retrained on the model's own base trees plus the domain's own parses; tagger and parser unchanged).

Invariant and cost

The split depends on the title alone: no round's window contains a dev or test article, and dev and test are the same in every round (checked again by the caller). A short pool is an error, never a short sample. Same inputs give byte-identical tables. Cost: reading ≀ train + 2Β·dev sentences from zstd frames; annotating dev and test twice; one adaptation that parses ≀ domain_max sentences and retrains the linearizer on base + domain; memory one model (β‰ˆ1.1 GB peak RSS measured).

Composition

main β†’ pool β†’ sample (read_article) β†’ tsv files β†’ Annotator::load (current or base) β†’ measure (dev, test) β†’ next_domain β†’ Model::adapt β†’ Annotator::save β†’ measure β†’ round.json. Called by the Eel's autoencoder round (tools/eel/src/autoencoder.rs), which pins this executable's hash and checks the sample files independently.

Behavior complement

Domain: rounds and pools. Relation: the module never writes outside --out, never installs, never reads the parser model, never trains the tagger or parser; with --lin-shuffle or --lin-reverse it learns from damaged windows (controls), never both. Counterexample: articles shorter than per_article make consecutive windows overlap slightly at their ends; a wrapped pool repeats windows (epoch > 0). Evidence: unit tests below, real hand runs.

Reverse reconstruction

Domain: round.json and the sample files. Relation: from (corpus, shards, sizes, k) the sample is recomputed exactly; from the candidate tables the window is not recoverable (the domain is capped and the linearizer is a many-to-one function of its training trees).

Tests

dev_is_fixed_and_never_in_any_train_window (red when the split admits held-out articles), rounds_take_fresh_windows_until_the_pool_wraps, a_small_pool_is_an_error_not_a_short_sample, domain_keeps_the_newest_lines, sentences_and_volumes_keep_the_text.

History

2026-11-06 Β· invariant-and-cost

Measured 2026-11-06 on shards 0..10 and 0..100, train 2,000, dev 500 and 2,000, 4 threads: round 5–17 s, child peak RSS 1.07–1.18 GB; the same round run twice gave byte-identical en-lin.bin. Dev 2,000 over 8 rounds: 382,333 β†’ 380,329 bits (tree layer only; frames and world unchanged), test 378,751 β†’ 377,049. --lin-reverse raised dev bits (refused); --lin-shuffle lowered them less than the window as written (99,338 β†’ 99,288 against β†’ 99,204).

Provenance

This page in Markdown β†’ https://md.groupants.elamur.ai/free/en/mova/tools/roundtrip/src/wiki.rs.groupant/