[build-system]
requires = ["hatchling>=1.21.0"]
build-backend = "hatchling.build"

[project]
name = "cleveragents"
version = "1.0.0"
description = "CleverAgents CLI and runtime toolkit"
readme = "README.md"
requires-python = ">=3.13"
license = {text = "MIT"}
authors = [
    {name = "CleverThis Engineering", email = "engineering@cleverthis.com"},
]
keywords = ["cleveragents", "ai", "cli", "automation"]
classifiers = [
    "Development Status :: 4 - Beta",
    "Intended Audience :: Developers",
    "License :: OSI Approved :: MIT License",
    "Programming Language :: Python",
    "Programming Language :: Python :: 3",
    "Programming Language :: Python :: 3.13",
]

dependencies = [
    # CLI Framework (ADR-009)
    "typer>=0.9.0",
    "uvicorn>=0.30.1",
    "fastapi>=0.115.0",
    "watchdog>=4.0.0",
    "faiss-cpu>=1.7.4",  # Vector store backend
    "rx>=3.2.0",  # Reactive streams for routing
    "dependency-injector>=4.41.0",  # DI container
    "pydantic>=2.7.0",
    "pydantic-settings>=2.11.0",
    "structlog>=24.4.0",
    "langchain>=0.2.14",
    "langchain-anthropic>=0.2.0",
    "langchain-community>=0.2.14",
    "langchain-openai>=0.2.0",
    "langchain-google-genai>=0.2.0",
    "jinja2>=3.1.0",
    "alembic>=1.13.1",
    "numpy>=2.1.0",
    "python-ulid>=2.7.0",  # ULID generation for plan/action IDs
    "RestrictedPython>=7.0",  # Secure sandbox for user-supplied code
    "jsonschema>=4.20.0",  # JSON Schema validation for tool inputs/outputs
    "tomlkit>=0.13.0",  # TOML writing with comment preservation for config CLI
    "tenacity>=8.2.0",  # Retry framework for service layer resilience
    "aiohttp>=3.13.4",  # CVE-2026-34515 mitigation: open redirect vulnerability
    "pyyaml>=6.0.3",  # CVE-2017-18342 mitigation: explicit pin to latest patched release; safe_load enforced throughout codebase
    "a2a-sdk>=0.3.0,<1.0.0",  # A2A Python SDK — required transport for local (stdio) and server (HTTP) modes (ADR-047); pinned <1.0.0 (removed legacy A2AClient)
]

[project.optional-dependencies]
tui = [
    "textual>=1.0.0,<2.0.0",
]
dev = [
    # Code formatting and linting
    "ruff>=0.15.0,<0.16.0",
    # Type checking
    "pyright>=1.1.350",
    "types-pyyaml>=6.0.0",
    "types-aiofiles>=23.0.0",
    # Testing
    "behave==1.3.3",
    "pytest>=8.0.0",
    "pytest-asyncio>=0.23.0",
    "pytest-cov>=4.1.0",
    # Pre-commit hooks
    "pre-commit>=3.6.0",
    # Security scanning
    "bandit[toml]>=1.7.5",
    "semgrep>=1.60.0",
    # Dead code detection
    "vulture>=2.10",
    # Complexity metrics
    "radon>=6.0.1",
]
tests = [
    "behave==1.3.3",
    "slipcover>=1.0.17",
    "asv>=0.6.5",
    "robotframework>=7.3.2",
    "robotframework-pabot>=4.0.0",
    "faker>=20.0.0",  # Dynamic test data generation
]
docs = [
    "mkdocs>=1.6.1",
    "mkdocs-material>=9.6.0",
    "mkdocstrings[python]>=0.24.0",
    "mkdocs-kroki-plugin>=1.2.0",
    "mkdocs-gen-files>=0.5.0",
    "mkdocs-literate-nav>=0.6.0",
    "griffe-pydantic>=1.0.0",
    "mkdocs-click>=0.8.0",
    "ruff>=0.4.0",
]

[project.urls]
Homepage = "https://cleverthis.com/cleveragents"
Documentation = "https://docs.cleverthis.com/cleveragents"
Repository = "https://git.cleverthis.com/cleveragents/core"
Issues = "https://git.cleverthis.com/cleveragents/core/issues"

[project.scripts]
cleveragents = "cleveragents.cli:main"
agents = "cleveragents.cli:main"

[tool.hatch.build.targets.wheel]
packages = ["src/cleveragents"]
include = [
    "src/cleveragents/py.typed",
    "src/cleveragents/infrastructure/database/migrations/alembic.ini",
    "src/cleveragents/infrastructure/database/migrations/script.py.mako",
    "src/cleveragents/infrastructure/database/migrations/README",
]

[tool.ruff]
line-length = 88
target-version = "py313"  # Target Python 3.13
src = ["src", "tests", "benchmarks"]
extend-exclude = ["docs/reference/contracts/stubs/*.py", "scripts/*.sh", "**/*.feature"]

[tool.ruff.lint]
select = ["E", "F", "W", "B", "UP", "I", "SIM", "RUF"]
ignore = []

[tool.ruff.lint.per-file-ignores]
"__init__.py" = ["F401"]
# Behave step files: F811 = redefined step_impl (Behave pattern), E501 = long step decorator strings
# B010 = setattr with constant attribute name is intentional in immutability tests (exercises frozen model enforcement)
# I001 = import sorting (Behave step files have specific import patterns)
"features/steps/*.py" = ["F811", "E501", "B010", "I001"]
"features/mocks/*.py" = ["E501"]
"features/environment.py" = ["E501"]
# retry_patterns.py re-exports symbols from retry_service_patterns at module bottom
"src/cleveragents/core/retry_patterns.py" = ["E402"]

[tool.ruff.format]
# Use double quotes for strings
quote-style = "double"
# Indent with 4 spaces
indent-style = "space"
# Unix line endings
line-ending = "auto"

[tool.pyright]
include = ["src"]
exclude = ["**/.nox", "**/__pycache__", "**/site-packages", "src/cleveragents/discovery"]
pythonVersion = "3.13"  # Target Python 3.13
typeCheckingMode = "strict"
strictListInference = true
strictDictionaryInference = true
strictSetInference = true
reportMissingImports = true
reportMissingTypeStubs = false
reportMissingTypeArgument = true
reportIncompatibleMethodOverride = true
reportIncompatibleVariableOverride = true
reportUnusedImport = true
reportUnusedClass = true
reportUnusedFunction = true
reportUnusedVariable = true
reportDuplicateImport = true
reportOptionalMemberAccess = true
reportOptionalCall = true
reportOptionalIterable = true
reportOptionalContextManager = true
reportOptionalOperand = true
reportTypedDictNotRequiredAccess = true
reportUnnecessaryIsInstance = true
reportUnnecessaryCast = true
reportUnnecessaryComparison = true
reportImplicitStringConcatenation = false
reportUnusedCallResult = false
reportUnknownMemberType = false
reportUnknownVariableType = false
reportUnknownParameterType = false

[tool.coverage]
# Coverage configuration

[tool.coverage.run]
source = ["src", "scripts"]
branch = true
parallel = false
omit = [
    "*/tests/*",
    "*/test_*",
    "features/*",
    "*/features/*",
    "*/__pycache__/*",
    "*/site-packages/*",
    "*/dependency_injector/*",
    "*/venv/*",
    "*/.venv/*",
    "*/.nox/*",
    "src/cleveragents/discovery/*",
]
data_file = "build/.coverage"

[tool.coverage.report]
# Single source of truth for the coverage floor (plan decision 2a). The
# nox engine and the worker diff-coverage gate read this via tomllib;
# slipcover does NOT auto-read pyproject, so callers pass --fail-under.
# Ratchet rule (decision 2b): objective is 97% — bump fail_under only AFTER
# observed master coverage has held >= target+buffer for N green commits.
# The 100%-patch diff-gate keeps total coverage monotonic, so this floor
# trails real coverage upward; it is not a precondition for shipping.
fail_under = 96.5

[tool.coverage.html]
directory = "build/htmlcov"

[tool.coverage.xml]
output = "build/coverage.xml"

[tool.bandit]
targets = ["src/cleveragents"]
exclude_dirs = [
    "tests",
    "features",
    ".nox",
    "build",
    "dist",
    "docs",
    "src/cleveragents/discovery",
]
# Severity level: LOW, MEDIUM, HIGH
severity = "MEDIUM"
# Confidence level: LOW, MEDIUM, HIGH
confidence = "MEDIUM"
# Skip specific tests if needed
skips = []

[tool.vulture]
min_confidence = 80
paths = ["src/cleveragents"]
exclude = ["src/cleveragents/discovery"]

[tool.hatch]
# Hatch build configuration

[tool.commitizen]
name = "cz_conventional_commits"
tag_format = "$version"
version_scheme = "pep440"
version_provider = "pep621"
update_changelog_on_bump = true
major_version_zero = true
