Contributing #

Thanks for taking the time to contribute. This document describes the local workflow, the quality bar enforced in CI, and how changes are reviewed.

Prerequisites #

make is convenient on Linux and macOS but is not required. python tasks.py is the cross-platform entry point and the source of truth; the Makefile simply delegates to it.

Getting set up #

uv sync --all-extras --dev     # or: python tasks.py setup
cp .env.example .env

Never commit a populated .env. .gitignore excludes it and CI runs a secret scan over both the working tree and the full git history.

Development loop #

Task Command
Format python tasks.py fmt
Lint python tasks.py lint
Type check python tasks.py typecheck
Unit tests python tasks.py test-unit
Integration tests python tasks.py test-integration
Security tests python tasks.py test-security
End-to-end journeys python tasks.py test-e2e
Scenario gate python tasks.py evaluate
Examples python tasks.py examples
Full suite + coverage gate python tasks.py test
Local security scans python tasks.py security
Container image python tasks.py docker-build
Container smoke test python tasks.py smoke

Run python tasks.py --list for the full list.

Quality bar #

A change is mergeable when all of the following hold:

  1. ruff check and ruff format --check are clean.
  2. mypy reports no errors.
  3. The full test suite passes and line coverage is at least 85%.
  4. bandit and pip-audit report no unresolved findings. If a dependency vulnerability has no upstream fix, add a justified, dated entry to security/audit-exceptions.md and the identifier to security/audit-ignores.txt.
  5. No secret scanner finding, in the tree or in history.
  6. python tasks.py evaluate is green. The scenario suite is gated at a 100% pass rate, with adversarial and identity categories gated separately, and a ceiling on escalation rate so an agent that hands everything to a human cannot pass by being cautious.
  7. Every example still runs. They are documentation that executes; one that stops working is a README that lies.

Tests #

Tests are grouped by pytest marker so each layer can run independently:

New behaviour needs a test at the lowest layer that can express it. Tests that assert nothing meaningful (assert True, smoke calls with no assertions) are rejected in review.

Two rules specific to this project:

Commits and pull requests #

Reporting security issues #

Do not open a public issue for a vulnerability. Follow the process in SECURITY.md.