Skip to content

Latest commit

 

History

History
50 lines (29 loc) · 2.35 KB

File metadata and controls

50 lines (29 loc) · 2.35 KB

Invariants

The numbered rules below are load-bearing. Every PR is checked against them; CI fails the build when one is violated. Add project-specific invariants in slots 6+ as your domain accretes.

1. Every contract crossing a module or process boundary is a StrictModel

Pydantic with extra="forbid" raises on unknown keys at construction. That kills the silent-key class of bug at the seam instead of three calls deep.

  • Where: src/models/_base.py
  • Enforced by: tests/test_models.py (asserts extra="forbid"); review.

2. API endpoints live under /api/v1/ and return typed responses

A versioned prefix means future breaking changes ship at /api/v2/ without coordinated client deploys. Typed responses mean an OpenAPI schema is correct by construction.

  • Where: src/api/routes.py
  • Enforced by: route review; FastAPI's response model inference.

3. Layer flow is one-way

api | evalagenttoolsdataobservabilitymodels. src.models imports nothing from src/. A reverse import collapses the layer story.

  • Where: pyproject.toml [tool.importlinter]
  • Enforced by: lint-imports job in CI; just architecture locally.

4. Coverage ≥ 75% on src/

Below 75 % the test suite stops being a meaningful gate; above ~90 % every PR slows down on coverage paperwork. 75 % is the load-bearing floor.

  • Where: pyproject.toml [tool.coverage.report] fail_under = 75
  • Enforced by: Coverage job in CI.

5. No secret leaves the repo unscanned

Three independent checkpoints (PreToolUse hook → pre-commit gitleaks → CI gitleaks) catch staged secrets before push, force-push, or merge. Once a secret is in the remote it is compromised forever.

  • Where: .claude/hooks/pretooluse_bash.py, .pre-commit-config.yaml, .github/workflows/security.yml
  • Enforced by: the three layers above.

6+. Project-specific invariants

Add invariants below as your domain stabilises. Each entry should describe:

  • The rule, in one sentence.
  • Where it lives (module or config file path).
  • Enforced by: test, review, or specific CI job.

Examples of the kind of invariant that earns a slot here: a domain-specific data contract that must validate at ingestion, a security boundary that must not log PII, a tool-call protocol that the agent must follow before the LLM emits a final response.