Conformance levels
An implementation’s conformance claim is a level, not a vibe. The levels are cumulative: claiming L(n) means L(0..n−1) hold too, and the shared corpus gates every level — fixtures are never edited to make an implementation pass.
The levels
Section titled “The levels”L0 — Notation. The text syntax parses and canonicalizes: every
documented construct round-trips (parse(to_text(m)) == m for every
model the implementation can represent), rejection is clean
(ParseError, never a crash), and the parser accepts exactly the
grammar the PARG contract describes.
L1 — Semantics. The parse is a semantic model, not typography: isotopes bind atoms, charges and oxidations are typed, bond kinds and directions are model data, reactions carry conditions. The wire form (asciichem-model v1) round-trips: model → wire → model is equal.
The perception pass is part of L1: chemistry the syntax leaves
implicit is derived once, as model services, and every implementation
must derive the same values. Today that covers implicit hydrogens
(aromatic bonds order 1.5 for H-counting, so c1ccccc1 and
C1=CC=CC=C1 perceive one hydrogen per carbon; a non-integral or
over-valent sum yields no answer rather than an invented one) and
aromatic rings (six-membered, fused-system sp2 rule; five-membered
rings are a documented limitation). The shared corpus pins both —
including the declines.
L2 — Render. Every model node renders to MathML (byte-golden against the corpus), canonical text, and the wire form. Rendering is deterministic across runs — visual and textual regression goldens exist for every construct.
L3 — Stereo. Tetrahedral parity (@/@@ → TH1/TH2), directional
bonds (/, \ → up/down), wedge/hash depiction semantics. Stereo
survives every round-trip (text, SMILES, wire, CML), enantiomers and
diastereomers stay distinct through the canonical form, and canonical
SMILES emits parity-correct tokens.
L4 — Identity. The model resolves to authoritative identity:
InChI/InChIKey via the opt-in engine, identifier cross-validation
(@inchi/@smiles/@cas checked against the structure), and
citation-grade resolution (one bibitem per (substance, source) the
author chose).
Current claims
Section titled “Current claims”| Level | Ruby (reference) | TypeScript | Python | Rust |
|---|---|---|---|---|
| L0 notation | yes | yes | yes | yes (canonical text) + parse contract — consumes the PARG artifact |
| L1 semantics | yes | yes | yes | yes (round-trip subset — model subset mirrors the reference TransformRules; out-of-subset constructs report unsupported) |
| L2 render | yes (MathML goldens, canonical text, wire) | yes (text, structural SVG, MathML goldens, wire) | yes (text, wire, MathML goldens, SVG byte-exact with TS) | yes (MathML goldens, canonical text, wire, SVG) |
| L3 stereo | yes — text, SMILES, wire, parity-correct tokens, ring closures | yes — chirality, directional bonds, parity-correct canonical SMILES | yes — chirality, directional bonds | no |
| L4 identity | yes — resolver + InChI engine (now native-capable: the NativeEngine drives the Rust engine’s C ABI; the binary engine remains the fallback) + OPSIN adapter + identifier cross-check shipped; sources settled: PubChem default, Common Chemistry opt-in (CC BY-NC, attributed) | partial (InChI via engine) | no | yes — the native engine (inchi-rs): full identifier, /t /m /s /b stereo layers, and the InChIKey natively computed, gated 1559/1559 against the recorded oracle corpus; reachable from Ruby through the NativeEngine and from Python/JS through its C ABI and bindings |
The matrix is regenerated from the conformance suite; a level claim without the green corpus run behind it does not ship.