Conformance
Two language-neutral conformance suites — 211 Core 1.0 cases and 136 References 2.0 cases — passed by TypeScript, Rust, and Go.
One of the standing criticisms of YAML is that different implementations routinely disagree with each other on ambiguous edge cases. Lima addresses this directly with a shared, implementation-independent conformance corpus, rather than tests written informally by each implementation’s own author. Two independently runnable targets exist today: 211 Core 1.0 cases and 136 References 2.0 cases. TypeScript, Rust, and Go pass both against the same expectations.
bun run run:core-1 # Core 1.0 — 211 cases
bun run run:references-2 # References 2.0 — 136 cases
What’s in it
- A byte-frozen 149-case Core 1.0.0 baseline
— count-pinned by a test and byte-protected by checked-in content-hash manifests so it cannot silently
drift. Core 1.0 has since grown to
211 cases via additive errata revisions through 1.0.9; each added case carries a
sincemarker and the 149-case baseline stays byte-identical. - A separate 136-case suite for Lima References 2.0, versioned independently and run on its own.
- Every case has exactly one expectation kind: a successful result, a thrown error, or warnings alongside a result.
- Case IDs are permanently stable and follow a fixed scheme:
core.numbers.safe-integer.maximum
core.strings.unknown-escape.strict
references-2.chains.maximum.three-edges-allowed
references-2.block-scalar.continuation.token-physical-line
Renaming an ID is treated as a corpus change, not a cosmetic edit.
An earlier References 1.0 was published briefly in mid-2026 and superseded almost immediately by References 2.0, which is deliberately not syntax-compatible with it. Its specification stays archived and its 101 frozen cases still run in CI as a regression guard on internal code — but it is not a target current implementations are asked to hit, and it is not counted here.
Why JSON, not YAML or Lima itself
The corpus format had to avoid two traps: describing tests in YAML would introduce YAML-native type semantics
into what’s supposed to be a language-neutral contract, and describing them in Lima would be circular — the
parser under test would be loading its own test definitions. JSON describes the test contract; the Lima input
itself stays verbatim, either inline as a JSON string or, when that would hurt readability, in a
.lima sidecar file.
Comparing by code, not by message text
Lima exposes a small, structured error API, and the corpus compares against it — not against full English error strings, which would tie every implementation to the exact wording of a TypeScript-first reference implementation.
type LimaDiagnosticCode =
| "INVALID_ESCAPE"
| "INVALID_QUOTE"
| "INVALID_DATE"
| "INVALID_NUMBER"
| "INVALID_REFERENCE_SHAPE"
| "INVALID_INDENTATION"
| "INVALID_FLOW_SYNTAX"
| "DUPLICATE_KEY"
| "RESOURCE_LIMIT"
| "UNRESOLVED_REFERENCE"
| "INVALID_INTERPOLATION"
| "INVALID_PARTIAL"
A diagnostic case compares the fields that are actually normative — code, line, and where relevant column, token, key, partial, path — never the prose message.
Language-neutral values
Host-language values that JSON can’t natively express — a UTC instant, NaN, -0, an intentionally invalid or out-of-range date — are represented as typed corpus values (e.g. { "$type": "instant", "value": "2024-03-01T09:00:00Z" })
that each runner materializes into its own native representation. This keeps a boundary case reproducible
across runners instead of depending on how, say, JavaScript’s
Date and a Rust date crate each happen to parse an arbitrary string.
Boundary values are generated, not hand-typed
Cases near a resource limit (§9 of Core, §6.2 of References) are produced by small, deterministic generators rather than pasted in by hand — a 16,385-code-point scalar or a 4,096-node partial is exactly the kind of input nobody should be hand-writing into a fixture file. Every generator is documented and reproducible across runners; generator semantics are part of the corpus contract itself.
Where this is going
The corpus is organized as versioned, independently runnable conformance targets, not one ever-growing pile of cases:
- Core 1.0 — 211 cases
(the byte-frozen 149-case 1.0.0 baseline plus 62 additive errata cases through 1.0.9). TypeScript (
@limaformat/lima), Rust (lima), and Go (github.com/limaformat/lima/go) all pass them against exactly the same expectations today. - References 2.0 — 136 cases, a separate suite. TypeScript, Rust, and Go each pass it (136/136) through their public References 2.0 APIs.
The suites remain separate conformance targets rather than one growing specification version. An implementation may legitimately claim Core 1.0 without claiming References 2.0. See Packages for implementation status per binding.
The full corpus, its schema, and the coverage matrices live in the repository:
corpus/,
design rationale in
docs/corpus-design/.