.. _contributing:

Contributing
============

Thank you for considering a contribution to llm-toolkit-schema!
This guide covers everything you need to get a development environment running,
write code that matches the project's standards, and submit a pull request.

Development setup
-----------------

.. code-block:: bash

   git clone https://github.com/llm-toolkit/llm-toolkit-schema.git
   cd llm-toolkit-schema
   python -m venv .venv

   # Windows
   .venv\Scripts\activate
   pip install -e ".[dev]"

   # macOS / Linux
   source .venv/bin/activate
   pip install -e ".[dev]"

Run the test suite:

.. code-block:: bash

   pytest                             # all tests
   pytest -m perf -v                  # NFR performance benchmarks only
   pytest --cov=llm_toolkit_schema -q         # with coverage report

Code standards
--------------

The project uses **ruff** for linting and formatting, and **mypy** for static
type checking.

.. code-block:: bash

   ruff check .       # lint
   ruff format .      # format
   mypy llm_toolkit_schema    # type check

All CI checks must pass before a PR is merged.  You can run them all at once
with:

.. code-block:: bash

   pre-commit run --all-files   # after: pre-commit install

Coverage requirement
---------------------

**100% branch coverage is required** on every commit.  No exceptions.
New code must come with tests that cover every branch.

.. code-block:: bash

   pytest --cov=llm_toolkit_schema --cov-fail-under=100 -q

Project layout
--------------

.. code-block:: text

   llm_toolkit_schema/
   ├── event.py           # Core Event + Tags dataclass
   ├── types.py           # EventType enum + helpers
   ├── ulid.py            # ULID generation and validation
   ├── signing.py         # HMAC signing, verify_chain, AuditStream
   ├── redact.py          # PII redaction framework
   ├── validate.py        # JSON Schema validation
   ├── migrate.py         # Migration helpers (Phase 9 scaffold)
   ├── models.py          # Pydantic v2 model layer (optional)
   ├── exceptions.py      # Domain exceptions
   ├── _cli.py            # CLI entry-point (coverage-omitted)
   ├── compliance/        # Compliance test suite
   │   ├── _compat.py     # test_compatibility (CHK-1…5)
   │   ├── test_chain.py  # verify_chain_integrity
   │   └── test_isolation.py  # verify_tenant_isolation
   ├── export/            # Export backends
   │   ├── otlp.py        # OTLP/Protobuf exporter
   │   ├── webhook.py     # HTTP webhook exporter
   │   └── jsonl.py       # JSONL file exporter
   ├── namespaces/        # Typed payload dataclasses
   │   ├── trace.py       # FROZEN v1 — llm.trace.*
   │   ├── cost.py        # llm.cost.*
   │   └── ...            # cache, diff, eval, fence, guard, prompt, redact, template
   └── stream.py          # EventStream routing + filtering

Adding a new namespace payload
-------------------------------

1. Create ``llm_toolkit_schema/namespaces/<name>.py`` following the existing pattern
   (frozen dataclass + ``validate()`` method + ``from_event()`` constructor).
2. Register the new ``EventType`` members in ``llm_toolkit_schema/types.py``.
3. Export the new payload class from ``llm_toolkit_schema/namespaces/__init__.py``
   and ``llm_toolkit_schema/__init__.py``.
4. Add tests in ``tests/test_namespaces.py`` — maintain 100% coverage.
5. Add a ``docs/namespaces/<name>.rst`` page.

Adding a new export backend
----------------------------

1. Create ``llm_toolkit_schema/export/<name>.py``.  Inherit from
   :class:`~llm_toolkit_schema.stream.Exporter` and implement ``export()`` and
   ``export_batch()``.
2. Export the class from ``llm_toolkit_schema/export/__init__.py``.
3. Add tests — ``tests/test_export_<name>.py``.
4. Document in ``docs/user_guide/export.rst``.

Commit messages
---------------

Use `Conventional Commits <https://www.conventionalcommits.org/>`_:

.. code-block:: text

   feat(signing): add key expiry validation
   fix(ulid): handle clock regression edge case
   docs(quickstart): add Kafka streaming example
   test(compliance): cover non-monotonic timestamp branch

Pull request checklist
-----------------------

Before opening a PR, confirm:

- [ ] ``pytest --cov=llm_toolkit_schema --cov-fail-under=100 -q`` passes
- [ ] ``ruff check .`` reports no errors
- [ ] ``mypy llm_toolkit_schema`` reports no errors
- [ ] New public API has Google-style docstrings
- [ ] ``CHANGELOG.rst`` updated under the *Unreleased* section
- [ ] Documentation updated if new public API was added

License
-------

llm-toolkit-schema is released under the `MIT License <https://github.com/llm-toolkit/llm-toolkit-schema/blob/main/LICENSE>`_.
By contributing you agree that your contributions will be licensed under the same terms.
