---
title: "modelcheck-undate — Mova code model"
description: "Mova code model of tools/modelcheck/src/undate.rs: components with their labels, obernants and the model text."
url: "https://groupants.elamur.ai/free/en/mova/tools/modelcheck/src/undate.rs.groupant/"
---
Elamur: [Mova](https://md.mova.elamur.ai/free/en/) · [Dictionary](https://md.dictionary.elamur.ai/free/en/) · [Research](https://md.research.elamur.ai/free/en/) · **Groupants**

This page as HTML: <https://groupants.elamur.ai/free/en/mova/tools/modelcheck/src/undate.rs.groupant/>

# modelcheck-undate

The groupant beside tools/modelcheck/src/undate.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

- **kind:** groupant
- **status:** partial source derived
- **source:** [`tools/modelcheck/src/undate.rs`](https://github.com/ElamurAI/mova-free/blob/main/tools/modelcheck/src/undate.rs)
- **repository folder:** [`tools/modelcheck/src/undate.rs.groupant`](https://github.com/ElamurAI/mova-free/tree/main/tools/modelcheck/src/undate.rs.groupant)

> **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

| component | label | where |
|---|---|---|
| **Approximant** | source derived | [Forward](#forward) |
| **Ast** | partial | `syntax.json` |
| **Cost** | symbolic unmeasured | [Cost](#cost) |
| **Descriptant** | present | [Descriptant](#descriptant) |
| **Invariant** | source derived | [Invariant](#invariant) |
| **Tests** | bounded executed | [Tests](#tests) |

## 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.

| relation | type | label | where |
|---|---|---|---|
| Behavior complement | behavior complement | partial source derived | [Behavior complement](#behavior-complement) |
| Reverse reconstruction | reverse reconstruction | partial source derived | [Reverse reconstruction](#reverse-reconstruction) |
| Line preservation | reverse reconstruction | bounded executed | [Line preservation](#line-preservation) |

## Model text


### Descriptant

`undate.rs` implements `mova-modelcheck undate REPO [--dry-run] NEW_REPORT`. The main blocks of a groupant `model.md` state what is now; dated material and provenance (digests, concrete run paths under the data directory) live verbatim in one final `## History` section. A section that a JSON record selects keeps its current substance: its dated sentences stay, mechanically rewritten without dates, while History keeps them verbatim; a selected section left heading-only gets its current body back from its newest History group. Mechanics only: no line is deleted, no model content is judged.

### Forward

Inputs: Git-visible files of REPO (tracked and nonignored untracked). Targets are files named `model.md` inside a `*.groupant/` directory. Protected names are every `section` value and every `model.md#Name` suffix in a tracked JSON string. The selection of a file is the set of its sections that some JSON record selects: `path` plus `section` in one object, or a `file.md#Section` value, resolved from the JSON file's directory.

1. Lines are classified outside code fences: blank, ATX heading, fenced, text. A heading block runs to the next heading of the same or a higher level (H1 lines end every block and never move). Text splits into units: a paragraph, one list item with its continuation, one table, one fenced block; a paragraph whose lines (except the last) each end a clause splits into record lines.
2. An epoch date is `YYYY-MM-DD` with year 2025 to 2029, not adjacent to digits; a toolchain build date `(<hex commit> DATE)` and a data snapshot date followed by ` run`, ` dump`, ` English dump` or ` snapshot` are not epoch dates. Provenance is a concrete path under the data directory variable (the variable followed by `/`, without a `<placeholder>`), a run of 40 or more lowercase hex digits that contains a digit, or seven or more such digits followed by `…`.
3. `strip_line` rewrites one line: a dated heading takes its undated name (Drop when nothing remains); an inline code span holding a date or provenance, a bare provenance token and a token in which a date is glued to an identifier become `(see History)`; a date is removed with its frame (`(D)`, `; D)`, `(D, `, a sentence-leading `Epoch D (…):` or `D,`, a preposition such as `as of`, `on`, `since`, or a separator such as `, D`, ` — D`, ` D:`), then spacing and punctuation are tidied and a sentence start is capitalized. A record line labelled `Date:`, `Run root:`, `Commit:` and similar, a History note, and a line left without letters or digits Drop. A heading holding provenance Fails. Fenced lines and lines without dates or provenance Keep unchanged.
4. Per H2 section: a unit with an epoch date or provenance goes to History; its key is its first date, else the date of the enclosing kept dated heading, else the last date seen earlier in the section, else `Undated`. In a selected section the unit also stays, rewritten line by line, when no line Fails and at least one line is kept. Otherwise it moves. A dated heading block moves whole, except the section lead: the first dated heading before any undated prose of the section stays in place under its undated name with a History note that quotes the original line. An undated block whose every unit moved moves whole, unless its name is a core block name (descriptant, domain, forward, reverse, invariant, cost, checks, tests, limits, limitations, composition, approximant); then only its units move and the heading stays. Code is neutral: it stays with a block that stays and moves with one that moves.
5. A dated H2 section moves whole unless protected. A dated H1 is renamed in place with a note.
6. Removal collapses the blank runs it leaves. History groups are `### <date> · <origin section>`, sorted by date with `Undated` last, stable in document order, consecutive equal groups merged; a moved block's top heading is raised to H4. An existing History is parsed into its groups and new entries merge into it.
7. `refill`: every selected H2 section with nothing but blank lines and headings gets a body inserted after its heading. The History groups of that origin are tried newest first (dated keys descending, `Undated` last); the first whose `restate` is nonempty wins. `restate` passes every line of the group through `strip_line`; a unit with a Failing line or with nothing kept is left out, a fence follows only a kept paragraph, a heading only kept content. History is not changed. A selected section that no group restates is reported as residue.
8. Every changed file passes `verify` and a second run returns it unchanged. Then fresh hash-bound JSON references (`path` plus `sha256` in one object) to changed files are rebound: a section's bytes for `model.md#S`, the whole file otherwise; JSON files changed by a rebind become targets of the next round until a fixpoint. Already stale bindings are reported and left stale. Without `--dry-run` all changed files are written. The report counts moved blocks and units, stripped units, refilled and residue sections.

### Invariant

Nonblank lines are preserved as a multiset when headings are compared without their `#` level; the only missing lines are dated headings renamed in place, each quoted by a History note; the only added lines are `## History`, group headings, notes, renamed headings and, inside selected sections of the main text, `strip_line` images of History lines (whose verbatim source History holds). Outside History and code fences no line carries an epoch date and no non-heading line carries provenance, except protected H2 headings. History is the single last H2 section. A second run is the identity. All maps are `BTreeMap`/`BTreeSet`, so two runs on the same tree give identical reports.

### Cost

One `git ls-files`, one read of every tracked JSON file and every groupant `model.md`. Per file a linear scan of L lines, O(L log L) for the History sort and the multiset verification, one `strip_line` pass over the History lines for the derivable set, and one repeated run for idempotence. `strip_line` is linear in the line length times the number of dates removed (at most 64). Rebinding scans the literals of every JSON file once per round; rounds stop at the fixpoint (at most 16).

### Tests

`undate::tests`: date detection with paper years, versions, seeds, toolchain build dates, data snapshot dates and invalid calendar values as non-dates; provenance digests and run paths, and the bare variable name as text; undated names; `strip_line` frames (parenthetical, sentence-leading epoch, preposition, separator, colon, code span, bare digest, run path, template path kept, glued run key, dated heading, record line and note dropped, heading with provenance failing, fenced line untouched); the A* fixture; protected and unprotected dated H2 sections; merging into an existing History; list items and tables; record lines against wrapped prose; a core heading kept; a selected section keeping its rewritten substance while an unselected one moves; refill of heading-only selected sections from the newest group (fence and sub-heading carried, older group ignored, `Undated` group used, record-only group left as residue, History unchanged); fresh, chained and stale hash bindings. Negative controls that `verify` must reject: a dropped line, a changed word, an invented line, a date left in the main text, a digest left in the main text, a rename without its note, a section after History, the untransformed dated text, a rewritten or refilled line outside a selected section, an invented refill line, and a refill line that keeps its date.

### Behavior complement

It does not delete lines, reorder lines inside a unit, edit fenced code, touch Markdown outside groupant `model.md` files, rename H2 sections that JSON selects, refresh stale hashes, edit the external groupant store, rewrite manifest `section` fields or statuses, or decide whether a dated statement is still true. Outside selected sections a paragraph that mixes a current statement with a date moves whole. A refill takes only the newest restatable group of the origin section; older groups and partially emptied sections stay as they are.

### Reverse reconstruction

Each History unit names its origin section in its group heading, and a moved block keeps its heading text, so the moved lines map back to their sections; a renamed heading maps back through its note. A rewritten or refilled main-text line maps back to its verbatim History line through `strip_line`, which is many-to-one (a removed date, frame or digest is not recoverable from the main text alone). Positions inside a section, blank-line spacing and the original heading levels of moved blocks are not recoverable from the output alone; Git history holds the exact former text.

### Line preservation

`verify(old, new, protected, selected)` is the executable reverse check of the invariant above, run on every changed file before any write; the unit tests above are its negative controls.

### Limits

Detection is lexical. A date written in another format, a digest shorter than 40 hex digits and not abbreviated with `…`, or a run path outside the data directory variable stays in the main text. `strip_line` removes frames by fixed patterns: a sentence may lose a parenthetical next to a leading date or read awkwardly after a removal; History holds the original. A section's lead is chosen by position, not meaning. Hash rebinding covers `path`/`sha256` pairs in one JSON object only.

## History


#### 2026-11-05 · Tests

First repository run, on the tree of the integration base plus this tool: 2,187 groupant `model.md` files, 2,089 changed; 1,208 heading blocks and 5,692 units moved, 834 headings renamed in place, one dated H2 kept because JSON selects it, no heading pushed past H6. 68 fresh hash bindings rebound in 28 JSON files; one already stale binding reported and left stale. Two dry runs gave byte-identical reports; a dry run after the write changed nothing. `groupants` (1,183 sidecars, 116 group sidecars, no diagnostics), `inventory --require-all` (1,183 of 1,183 Rust files) and the correspondence scan passed afterwards. 1,078 H2 sections lost all their text to History, 210 of them under core block names (72 descriptant, domain, forward, invariant, cost or approximant): explicit gaps for current undated statements.

Second version, on the tree of the integration base plus this tool: 2,190 groupant `model.md` files, 638 changed. 729 selected sections that the first run had left heading-only were refilled from their newest History group (449 `epoch-memory`, 70 `tests`, 33 `evidence`, 23 `checks`, 21 `cost`, …); no residue. One unit of a selected section stayed rewritten; nothing moved. 11 fresh hash bindings rebound in 11 JSON files, none stale. A run after the write changed nothing. With the new empty-selection gate, `groupants` on the integration base reported 1,047 component diagnostics (heading-only sections under statuses that claim content); after the refill none.

## Provenance

- **source SHA-256:** `b084dc7276ec4cbc…`
- **repository commit:** `1c97be5c5883`
