Development Guide¶
This guide covers development workflows, tooling, and advanced features for contributors.
Quality Tooling Stack¶
| Tool | Purpose | Command |
|---|---|---|
| Ruff | Linting + formatting | poetry run ruff check src tests |
| Mypy | Static type checking | poetry run mypy --strict src/nhra_gt |
| Pytest | Testing framework | poetry run pytest |
| Hypothesis | Property-based testing | Integrated with pytest |
| Pre-commit | Git hooks | pre-commit run --all-files |
| Bandit | Security scanning | poetry run bandit -r src |
| Deptry | Dependency hygiene | poetry run deptry . |
Running Tests¶
Basic Test Run¶
With Coverage¶
Specific Test Files¶
# Run only game tests
poetry run pytest tests/test_games.py
# Run with verbose output
poetry run pytest -v
# Stop on first failure
poetry run pytest -x
Property-Based Tests¶
We use Hypothesis for property-based testing:
Performance Profiling¶
Scalene (Recommended)¶
We use Scalene for high-performance CPU, GPU, and memory profiling:
# Profile the backtest loop
LOGFIRE_SEND_TO_LOGFIRE=false PYTHONPATH=src \
scalene --cli --profile-all scripts/validation/recursive_backtest.py
py-spy (Sampling Profiler)¶
For low-overhead production profiling:
memray (Memory Profiling)¶
JAX Acceleration & Functional Core¶
The project uses a high-performance JAX/XLA functional core for the simulation engine. This allows for 10-100x speedups via vectorization and hardware acceleration.
Functional Programming Rules¶
To maintain JIT-compatibility, all code in src/nhra_gt/engine.py must be purely functional:
- No Side Effects: No
print(), no global variable mutations, no in-place array updates. - No Python Control Flow: Use
jax.lax.cond,jax.lax.switch, andjax.lax.scaninstead ofif,elif, andfor. - Statelessness: Use
StateJaxPytrees instead of objects withself.
Pytree State Management¶
System state is managed using flax.struct.dataclass. This allows JAX to treat complex objects as unified blocks of memory:
from nhra_gt.domain.state import StateJax
# Transformation (returns a new state)
new_state = state.replace(pressure=1.2)
Vectorization (vmap)¶
Use jax.vmap to run thousands of Monte Carlo samples or all 8 Australian jurisdictions in parallel at near-zero extra cost:
# Run 1000 rollouts in parallel
keys = jax.random.split(key, 1000)
parallel_results = jax.vmap(run_simulation)(keys)
Performance & Caching¶
The engine automatically uses a persistent disk cache for compiled XLA kernels located at ~/.cache/jax_cache. This minimizes "Time-to-First-Plot" in the dashboard.
To run performance benchmarks:
Snakemake Pipelines¶
The project uses Snakemake for reproducible pipelines.
Available Targets¶
# Run baseline simulation
poetry run snakemake --cores 4 run_baseline
# Build context pack
poetry run snakemake --cores 4 context_pack
# Run all experiments
poetry run snakemake --cores 4 all
# Dry run (show what would execute)
poetry run snakemake -n all
Visualize DAG¶
CI/CD Pipeline¶
The GitHub Actions CI runs on every push and PR:
- Lint — Ruff check and format
- Type Check — Mypy strict mode
- Security — Bandit scan (Ubuntu/3.12 only)
- Dependency Hygiene — Deptry (Ubuntu/3.12 only)
- Input Traceability — Parameter grounding check
- Context Pack — Build and verify
- Tests — Full pytest suite
- Pipeline — Snakemake verification
- Docs — MkDocs build
- Link Check — Lychee markdown link validation
Matrix¶
Tests run across:
- OS: Ubuntu, macOS, Windows
- Python: 3.10, 3.11, 3.12, 3.13
Observability (Optional)¶
For production observability, we support Logfire:
# Install observability extras
poetry install --extras observability
# Enable Logfire
export LOGFIRE_SEND_TO_LOGFIRE=true
python scripts/run_baseline.py
Debugging Tips¶
Common Issues¶
| Issue | Solution |
|---|---|
| Import errors | Ensure PYTHONPATH=src is set |
| Type errors | Run poetry run mypy --strict src/nhra_gt |
| Test failures | Check poetry run pytest -v for details |
| Slow builds | Use poetry run mkdocs serve for live reload |
Debug Logging¶
Or via environment:
See Also¶
- Contributing Guide — How to contribute
- Usage Guide — Getting started
- API Reference — Module documentation