Hand-curated catalogue of equivalent or near-equivalent
tactics and lemma names across Isabelle/HOL, Coq/Rocq, and Lean 4 (with
or without mathlib). Used by the planned echidna suggest CLI verb
(see ECHIDNA-NOTES-2026-04-27.md §4.1) and by the variant-tester
loop (§4.3) to recover from "synonym blindness" failures — proofs that
go through under one name but fail under another.
Fourteen files, one per backend with a curated table:
| File | Prover |
|---|---|
|
Isabelle/HOL (Isabelle2025+ — older versions noted per-entry) |
|
Coq 8.18+ / Rocq |
|
Lean 4 + mathlib4 |
|
Agda |
|
Idris 2 ( |
|
Isabelle/AFP naming |
|
Metamath |
|
Mizar MML |
|
HOL4 |
|
HOL Light |
|
Dafny |
|
Why3 / WhyML |
|
F* |
|
ACL2 |
The first 20+ entries were seeded by Opus on 2026-04-27 from the two
ECHIDNA-discovered drifts during the tropical-resource-typing fix
session (induct→induction, add_le_add→add_mono) and from
hand-knowledge of common idiom drift across mathlib / mathcomp /
Isabelle’s Main.
Underscore-prefixed files are not per-prover tables. They are loaded as
secondary indices by SynonymTable::with_*() / load_cross_prover_dicts
(Rust) and SaturationSynonyms.load_*(dir) (Julia), and exist so that
corpus items can be joined across systems by semantic_class.
| File | Rows (2026-10-22) | Scope |
|---|---|---|
|
181 |
MSC2020 codes. 68Qxx (theory of computing) and 68Nxx (theory of software) are complete; 03B/03C/03D/03F cover logic, computability and proof theory; 68M/68P/68T/68V/68W cover systems, data, AI and proof assistants. |
|
81 |
WordNet 3.1 math senses. Undergraduate / textbook pure mathematics. |
|
53 |
ConceptNet 5.7 edges, pre-fetched for the offline S5 gate. |
|
41 |
The 42 TypeChecker disciplines (see
|
|
665 |
Program verification: bitvectors and machine integers, memory layout and ABI, ownership and slicing, separation logic and region framing, contracts and proof obligations, termination measures, refinement, resource algebras (dioid / tropical / antichain), information flow and epistemic vocabulary, concurrency, and estate layering. |
_verification_systems.toml exists because the WordNet and ConceptNet
dictionaries are anchored in competition and undergraduate pure
mathematics (the same shape as the ProofNet and MiniF2F corpora). The
concepts this repository’s own verification surface is written in — zero_extend, wrapping_add, alignment_power_of_two, slice_disjoint,
frame_rule, decreases_clause, noninterference_tini — had no
semantic_class at all, so the cross-prover join silently dropped them.
The vocabulary follows the estate’s language policy, and rows are named to match it:
-
ABIs are Idris2 (
abi_contract,idris2_abi,foreign_descriptor). -
APIs and FFIs are Zig (
zig_api,zig_ffi,calling_convention). -
BEAM native boundaries are SNIFs, never bare NIFs (
snif,snif_contract,scheduler_thread,term_lifetime). -
The Rust layer is Rust/Creusot (
creusot_annotation,rust_creusot_layer), Julia owns the numeric/ML layer, Chapel the parallel layer. -
Python is not part of the estate. No table, script or verification path may require a Python runtime.
| Field | Required? | Meaning |
|---|---|---|
|
yes |
Preferred / current name. Variant testers prefer this when emitting suggestions. |
|
yes |
Array of non-empty names; |
|
no |
Coarse category ( |
|
no |
Free-text rationale, version notes, or pitfalls. |
|
no |
Version range over which the alias applies. Empty means "always". |
Owner decisions 2026-10-19 (D2, D4) in
docs/decisions/2026-10-19-lexicon-v2-and-identity-arbitration.adoc.
All fields are optional; v1 rows load unchanged. The schema of record is the
Nickel contract schema.ncl; scripts/lexicon-check.sh (or
just lexicon-check) applies it to every table here and to the fixtures in
tests/lexicon_fixtures/, and CI runs it in the rust-ci check job.
| Field | Meaning |
|---|---|
|
How |
|
Token list of a multi-token idiom. Required with, and only allowed with,
|
|
Look-alike names in other tables, each |
|
The witness behind the row: |
|
|
|
|
Corpus-mined candidates (owner decision D4) are flag-only: they carry
evidence = { kind = "none" } and never set semantic_class on their own.
Nickel checks shape and the cross-field rules; serde checks that
checked_by names a ProverKind and format an ExchangeFormat when Rust
loads a table (tests/lexicon_v2_test.rs).
When echidna suggest encounters a tactic name in a failing proof, it:
-
Looks up the name in the appropriate prover’s table.
-
For each entry where the name is
canonicalor inaliases, it tries substituting every other alias (and the canonical) in turn. -
Re-runs the proof with each substitution.
-
Reports successful substitutions, ranked by edit minimality.
The tester is deliberately mechanical — no search, no creativity, no ML. It only catches the cases where the proof author used a name the prover no longer accepts (or never accepted in this version).
-
Cross-prover synonym graph (Isabelle
le_trans↔ CoqRle_trans↔ Leanle_trans) is intentionally out of scope here — that’sechidna port, notechidna suggest. -
ML-driven synonym discovery from the corpus (mining
training_data/) is in §4.4 of the notes, not this layer.