Skip to main content

emlint

emlint logo

PyPI version Python versions CI Codecov Documentation License Downloads

stim simulates. sinter samples. emlint verifies.

emlint is a static linter for Stim Detector Error Models (DEMs). It finds structural problems before simulation.

Why emlint?

  • Catch DEM bugs before the expensive simulation. A silent DEM bug can inflate logical error rates and may not surface until 10⁶ simulation shots (≈45 min). emlint finds structural problems in milliseconds.
  • Counter-examples. A failing check identifies the offending mechanism, detector, or observable, so you know where to look.
  • Severity that respects the stakes. error findings are unconditional DEM bugs; warning findings are heuristic or intentional-pattern candidates you review before acting.
  • Agent- and CI-friendly. Exit codes distinguish clean, error, warning, and unlintable input; JSON and SARIF output feed scripts and code-scanning tools.

See it in action

A d=5 surface-code DEM with a missing detector connection (examples/buggy.dem):

$ emlint check examples/buggy.dem
Detectors: 24  Observables: 1  Error mechanisms: 31
DEM-only analysis: findings do not establish circuit semantic correctness.

  ✓ detectability: All error mechanisms that flip observables also trigger detectors.
  ✗ [warning] sensitivity: 1 detector(s) are never triggered by any error mechanism.
        Counter-example: Detector(s) not triggered by any error mechanism: D17@(1,0,2)
        Hint: Hypothesis: a detector no mechanism ever triggers is either miswired or
        redundant. Expected shape: at least one mechanism per stabilizer check per
        round; look for a missing noise instruction on the gates feeding this detector,
        or a DETECTOR declared on a comparison that never receives a fault. Limit: a
        detector with a constant outcome (fires every shot, or never fires) also has no
        mechanism in the DEM, so it is indistinguishable from a dead detector here;
        check the reference sample before treating this as a wiring bug.
  ✓ observable_coverage: All declared observables are flipped by at least one error mechanism.
  ✓ probability_bounds: All error mechanism probabilities are finite and strictly positive.
  ✓ duplicates: No duplicate mechanism signatures found.
  ✓ correctability: Every syndrome maps to at most one distinct set of logical observables.
  ✓ null_mechanism: No mechanism has empty detector and observable support.
  ✓ high_probability_mechanisms: All mechanism probabilities are ≤ 0.3.
  ✗ [warning] connectivity: Decoding graph has 2 connected components.
        Counter-example: Component 1: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
        15, 16, 18, 19, 20, 21, 22, 23]; Component 2: [17]
  ✓ boundary_symmetry: Skipped: fewer than 2 logical observables (boundary symmetry requires ≥ 2).

After reconnecting D17 to its neighbours (examples/fixed.dem), every check passes. The counter-examples name the exact detector (D17@(1,0,2)) and the isolated decoding-graph component ([17]), so the fix is localized. More generated examples live in examples/.

v0.2 is preliminary. The user-facing behavior is usable, but internal APIs and implementation details may change before v1.0.

Quick start

Install emlint:

pip install emlint

Lint a DEM file or raw DEM text:

emlint check circuit.dem
emlint check 'error(0.01) D0 L0
detector D0'

A failing result includes a counter-example identifying the relevant mechanism, detector, or observable. Select checks with --only/--ignore, or emit SARIF for code-scanning tools:

emlint check circuit.dem --only detectability,sensitivity
emlint check circuit.dem --format sarif > emlint.sarif

Project defaults can be placed in pyproject.toml under [tool.emlint]. For all command options, configuration examples, and exit codes, see the CLI reference.

Python

import emlint
import stim

circuit = stim.Circuit.generated(
    "surface_code:rotated_memory_z",
    distance=3,
    rounds=3,
    after_clifford_depolarization=0.001,
)
report = emlint.check(circuit.detector_error_model())
print(emlint.format_text(report))

emlint.check() also accepts a raw DEM string or an explicit pathlib.Path.

Documentation

Guide Use it for
CLI reference Commands, options, output, and exit codes
Agent integration guide Running emlint in a coding-agent fix-loop: exit-code handling, JSON contract, context declaration
Check catalog What the seven checks detect and how to interpret findings, plus the machine-readable output contract
Debugging guide Check-specific causes and investigation steps
Formal grounding DEM vocabulary and formal properties
v0.2 limitations Scope, warnings, repeat blocks, and provisional behavior
Changelog Version history and user-visible changes

Note: on DEMs produced with decompose_errors=True, the duplicates check (warning) may report mechanisms that share a detector signature after graphlike decomposition as "duplicates". This is expected decomposition output, not a concatenation bug. The graphlike-decoder profile requires an explicit decoder context for compatibility checks; it does not suppress this warning, which can still make a correct DEM exit with code 2. Use --ignore duplicates only when you deliberately want to skip this advisory check.

Exit codes

Code Meaning
0 All checks passed
1 At least one error-severity finding
2 Warnings only
3 Unlintable input (unreadable or unparseable)

Treat exit code 3 as an input failure, not as findings: an agent loop that parses the report on exit 3 would reason about a DEM that emlint never saw.

Epistemic boundary: emlint analyzes DEMs only. Its findings establish structural properties of the DEM itself; they do not establish that the underlying circuit is semantically correct, nor that a decoder succeeds. Circuit-level verification (e.g. with stim) remains necessary.

CI

For a minimal GitHub Actions setup, install emlint and run it on changed DEM files:

- name: Install emlint
  run: pip install emlint
- name: Lint DEM files
  run: find . -name "*.dem" -print0 | xargs -0 -r -n1 emlint check

For local commits, the repository includes a pre-commit hook configuration:

pip install pre-commit
pre-commit install

The hook runs emlint check --severity error on staged .dem files. Warning-only findings remain non-blocking; input failures still return exit code 3.

Contributing

See CONTRIBUTING.md for development setup, how to add a check, test requirements, and quality gates.

Acknowledgments

emlint is developed with AI assistance for scaffolding, test generation, red-teaming, and documentation. All design decisions, technical content, and final code are reviewed and owned by the maintainers.

Funding

This project is funded by a Mozilla Foundation fellowship and supported by the Unitary Foundation.

License

Apache 2.0

Metadata

Release files for emlint 0.2.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for emlint 0.2.4
File Size Uploaded Provenance Actions
emlint-0.2.4.tar.gz 113.1 kB With provenance Details for emlint-0.2.4.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for emlint 0.2.4
File Interpreter ABI Platform Actions
emlint-0.2.4-py3-none-any.whl Python 3 none any Details for emlint-0.2.4-py3-none-any.whl

Total release size: 163.4 kB

Release files / emlint-0.2.4.tar.gz

Download URL emlint-0.2.4.tar.gz
Size 113.1 kB
Tags Source
SHA-256 checksum
How to use checksums
dd5196ace31098ad855249f38799a235c98db150f37d9bf7281d04df29470775
BLAKE2b-256 checksum
How to use checksums
391bd95e3abdcf8a2d893a146a70c6e874abdf110e81a54110dc3bfc7213340c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.

Transparency log

Release files / emlint-0.2.4-py3-none-any.whl

Download URL emlint-0.2.4-py3-none-any.whl
Size 50.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
210167b055c3f155628b5f86589f2a1a0f102ec983f055e327840eeceeec11e5
BLAKE2b-256 checksum
How to use checksums
ddf3d2f427912f3474a4a57cf6ea8226b23e1669a42e46bc96a4d7bb8a8c67e6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.

Transparency log

Security for emlint 0.2.4

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for emlint-0.2.4.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page