|
| 1 | +# Contributing to gateframe |
| 2 | + |
| 3 | +Thank you for your interest in contributing. This document covers how to set up a dev environment, how to add new rule types and integrations, and what the PR process looks like. |
| 4 | + |
| 5 | +--- |
| 6 | + |
| 7 | +## Dev setup |
| 8 | + |
| 9 | +```bash |
| 10 | +git clone https://github.com/practicalmind-ai/gateframe.git |
| 11 | +cd gateframe |
| 12 | +pip install -e ".[dev]" |
| 13 | +python -m pytest tests/ -v |
| 14 | +``` |
| 15 | + |
| 16 | +Lint and format: |
| 17 | + |
| 18 | +```bash |
| 19 | +ruff check gateframe/ tests/ examples/ |
| 20 | +ruff format --check . |
| 21 | +ruff format . |
| 22 | +``` |
| 23 | + |
| 24 | +All tests must pass and both checks must be clean before a PR is mergeable. |
| 25 | + |
| 26 | +--- |
| 27 | + |
| 28 | +## Project structure |
| 29 | + |
| 30 | +``` |
| 31 | +gateframe/ |
| 32 | +├── core/ # ValidationContract, WorkflowContext, FailureMode, EscalationRouter |
| 33 | +├── rules/ # StructuralRule, SemanticRule, BoundaryRule, ConfidenceRule |
| 34 | +├── integrations/ # OpenAI, Anthropic, LiteLLM, LangChain |
| 35 | +├── audit/ # AuditLog, exporters |
| 36 | +└── cli/ # inspect, replay subcommands |
| 37 | +tests/ # mirrors gateframe/ structure |
| 38 | +examples/ # runnable end-to-end examples |
| 39 | +``` |
| 40 | + |
| 41 | +--- |
| 42 | + |
| 43 | +## How to add a new rule type |
| 44 | + |
| 45 | +1. Create `gateframe/rules/<name>.py` with a single class inheriting from `Rule`. |
| 46 | +2. Implement `validate(self, output, **context) -> FailureResult | None`. Return `None` on pass. |
| 47 | +3. Catch all exceptions inside `validate` — never let them propagate. Return a `FailureResult` with the exception message instead. |
| 48 | +4. Choose a default `failure_mode` that fits the severity: `HARD_FAIL` for scope or authority violations, `SOFT_FAIL` for confidence or quality degradation. |
| 49 | +5. Write actionable error messages. `"Validation failed"` is not acceptable. `"Confidence 0.42 is below minimum threshold 0.7."` is. |
| 50 | +6. Add the class to `gateframe/__init__.py` and the `__all__` list so it is part of the public API. |
| 51 | +7. Create `tests/rules/test_<name>.py`. Cover: happy path, failure path, exception handling, custom failure mode, context forwarding, and the default name. |
| 52 | + |
| 53 | +--- |
| 54 | + |
| 55 | +## How to add a new integration |
| 56 | + |
| 57 | +1. Create `gateframe/integrations/<provider>.py`. |
| 58 | +2. Add a `_require_<provider>()` guard that raises `ImportError` with install instructions if the SDK is not available. |
| 59 | +3. Implement `extract_text`, `extract_json`, and `extract_metadata` as standalone functions (not methods). Keeping them separate from the validator class makes them individually testable. |
| 60 | +4. Implement a `<Provider>Validator` class that accepts a `ValidationContract` and optional config, and calls the extract functions inside `validate()`. |
| 61 | +5. Add the optional dependency to `pyproject.toml` under `[project.optional-dependencies]`. |
| 62 | +6. Create `tests/integrations/test_<provider>.py`. Use dataclasses to mock provider responses — no real API calls. Cover all three extract functions and the validator class. |
| 63 | + |
| 64 | +--- |
| 65 | + |
| 66 | +## Testing requirements |
| 67 | + |
| 68 | +- Every failure path must be tested, not just the happy path. |
| 69 | +- Use dataclasses to mock provider responses, not `unittest.mock` or real API calls. |
| 70 | +- Tests mirror the source tree: `gateframe/rules/boundary.py` → `tests/rules/test_boundary.py`. |
| 71 | +- Construction-time errors (e.g. `ValueError` for bad rule configuration) are tested separately from validation failures. |
| 72 | + |
| 73 | +--- |
| 74 | + |
| 75 | +## Code style |
| 76 | + |
| 77 | +- No `print` in library code. Use `structlog` for all internal logging. |
| 78 | +- No unnecessary docstrings or comments. Code should be self-explanatory. |
| 79 | +- Type hints required everywhere. `Any` requires a comment explaining why. |
| 80 | +- One class per file where possible. |
| 81 | +- Error messages must be actionable — include what failed, the actual value, and the expected value or constraint. |
| 82 | +- Python 3.10+. No dependencies in core beyond `pydantic>=2` and `structlog`. |
| 83 | + |
| 84 | +--- |
| 85 | + |
| 86 | +## PR process |
| 87 | + |
| 88 | +1. Fork the repository and create a branch from `main`. |
| 89 | +2. Make your changes. If you're adding a feature, add tests for it. |
| 90 | +3. Run `python -m pytest tests/ -v` — all tests must pass. |
| 91 | +4. Run `ruff check gateframe/ tests/ examples/` and `ruff format --check .` — both must be clean. |
| 92 | +5. Open a pull request with a description of what the change does and why. |
| 93 | + |
| 94 | +If you're unsure whether a change fits the scope of the project, open an issue first. |
0 commit comments