diff --git a/AGENTS.md b/AGENTS.md index f5f357a..94395c4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -33,6 +33,7 @@ This repository owns the published `elydora` package, its CLI, synchronous and a ## Code Quality +- Keep the package, distribution, and CLI version in `elydora/_version.py`; build metadata must read that literal through Setuptools dynamic metadata. - Support every Python version declared in `pyproject.toml`. - Keep production source files at or below 500 lines. - Keep functions focused on one ownership boundary. diff --git a/elydora/__init__.py b/elydora/__init__.py index c210404..c66352e 100644 --- a/elydora/__init__.py +++ b/elydora/__init__.py @@ -3,6 +3,7 @@ from .client import ElydoraClient from .async_client import AsyncElydoraClient from .errors import ElydoraError +from ._version import __version__ from .crypto import ( compute_chain_hash, compute_payload_hash, @@ -70,9 +71,8 @@ from .types import ( DeepHealthResponse, ) -__version__ = "1.2.0" - __all__ = [ + "__version__", "ElydoraClient", "AsyncElydoraClient", "ElydoraError", diff --git a/elydora/_version.py b/elydora/_version.py new file mode 100644 index 0000000..6b481aa --- /dev/null +++ b/elydora/_version.py @@ -0,0 +1,3 @@ +"""Canonical Elydora package version.""" + +__version__ = "1.2.1" diff --git a/elydora/cli.py b/elydora/cli.py index bdee298..ce0d8f3 100644 --- a/elydora/cli.py +++ b/elydora/cli.py @@ -14,6 +14,7 @@ import shutil import sys from typing import Dict, Type +from ._version import __version__ from .crypto import get_public_key_base64url from .plugins.base import AgentPlugin, InstallConfig from .plugins.registry import SUPPORTED_AGENTS, get_agent_names @@ -174,7 +175,7 @@ def build_parser() -> argparse.ArgumentParser: description="Elydora — tamper-evident audit trail for AI agents", ) parser.add_argument( - "--version", action="version", version="%(prog)s 1.0.0" + "--version", action="version", version=f"%(prog)s {__version__}" ) subparsers = parser.add_subparsers(dest="command", help="Available commands") diff --git a/pyproject.toml b/pyproject.toml index 7add10c..cdeebad 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "elydora" -version = "1.2.1" +dynamic = ["version"] description = "Python SDK for the Elydora tamper-evident audit platform" readme = "README.md" license = {text = "MIT"} @@ -41,3 +41,6 @@ dev = [ [tool.setuptools.packages.find] include = ["elydora*"] + +[tool.setuptools.dynamic] +version = {attr = "elydora._version.__version__"} diff --git a/tests/test_version_contract.py b/tests/test_version_contract.py new file mode 100644 index 0000000..4cca48c --- /dev/null +++ b/tests/test_version_contract.py @@ -0,0 +1,18 @@ +from importlib.metadata import version + +import pytest + +from elydora import __version__ +from elydora.cli import build_parser + + +def test_runtime_version_matches_distribution_metadata() -> None: + assert __version__ == version("elydora") + + +def test_cli_reports_the_canonical_version(capsys: pytest.CaptureFixture[str]) -> None: + with pytest.raises(SystemExit) as exc_info: + build_parser().parse_args(["--version"]) + + assert exc_info.value.code == 0 + assert capsys.readouterr().out == f"elydora {__version__}\n"