build/
dist/
*.egg-info/
__pycache__/
*.pyc
*.so
*.pyd
# The wfmgen CLI binary CMake bundles into the package for the wheel — a build
# artifact (platform-specific, rebuilt every build), never committed. The wheel
# build copies it in at package time; a source checkout regenerates it.
src/doppler/wfm/_bin/
.venv/
compile_commands.json
ffi/rust/target/
/consumer.cf32

# Generated documentation output
docs/doxygen/
site/
.capi-site/

# Example / benchmark artifacts written to the working tree (regenerable;
# belong in build/, never committed to the repo root)
/*.png
/bench_*.json
# `.csv` was missing here, and one got committed: `agc_step_response.csv`,
# 206 KB at the repo root, added by f79ac33f — the very commit that
# introduced the fail-closed example gate on the principle that an example
# must never pollute the repo. The C demo `build/native/examples/agc_demo` writes
# it into whatever cwd it is run from, and docs/examples/c.md tells you to
# run it from the root. Root-scoped, so the validation trees' deliberately
# committed `*/data/*.csv` are untouched.
/*.csv

# A characterization subject's plot, written beside its characterize.py by
# `make characterize`. A working artifact, not a deliverable: the sweep's
# findings go to stdout, and a subject with a published page has its plot
# regenerated into docs/assets/ by `make gallery` instead. Committing both
# copies is what let the published one sit a month stale behind the code
# that produced it.
src/doppler/*/tests/characterization/*/*.png

# benchmarks/history/ is local scratch from `make bench`. The canonical,
# committed numbers live in benchmarks/published/v<ver>/ (representative,
# measured by hand — see docs/dev/release.md §2b). Only the .gitkeep here.
benchmarks/history/*
!benchmarks/history/.gitkeep

# pytest-benchmark's default --benchmark-save store (the project keeps its own
# numbers under benchmarks/; this tool cache is never committed).
.benchmarks/

# doxygen local output (CI generates these; never commit)
html/
xml/

# jm re-materializes this Zensical scaffold file, but the site uses mkdocs.yml
# (`make docs` deletes it, since a stale one shadows mkdocs.yml).
#
# Anchored to the ROOT: unanchored, it also swallowed the copy jm scaffolds for
# the nested project in examples/downstream-jm/, whose own drift gate then
# reported it permanently missing. This rule is about doppler's own file.
/zensical.toml
build-cov/
build-ubsan/
build-tsan/
# `make glibc-gate` builds here, inside the bind-mounted checkout, so the
# container's Debian 10 tree never collides with the dev's own build/.
build-glibc228/
# `make ci-run` / `make ci-gates` build here for the same reason: the CI image
# and the host target different glibcs, so one shared build/ produces link
# errors that read like code bugs. Missing this line cost a `git add -A` that
# swept 20k generated files into the index and set the end-of-file fixer
# loose on them -- an ignore rule is not bookkeeping, it is what keeps a
# bind-mounted build tree out of the repository.
build-ci/
.mkdoxy/

# jm materialises its own create-only assertion harness on every `jm apply`.
# doppler does not use it: the C tests run on `native/tests/dp_test.h`, and
# `scripts/check_tests_ssot.py` enforces that every macro and helper is owned
# by one of the dp_*.h harness headers -- so committing jm_test.h would add a
# second, unused assertion vocabulary alongside the one that gate protects.
# Ignored rather than deleted each time, because `jm apply` recreates it and
# the drift gate is green either way (verified: exit 0 with it absent).
native/tests/jm_test.h
