[build-system] requires = ["hatchling"] build-backend = "hatchling.build" [project] name = "better-code-review-graph" version = "3.26.18" description = "Token-efficient code review knowledge graph: semantic search and call-graph resolution." readme = { file = "README.md", content-type = "text/markdown" } license = "Apache-2.0" requires-python = "==3.13.*" authors = [{ name = "n24q02m" }] keywords = ["code-review", "knowledge-graph", "tree-sitter", "claude-code", "mcp", "mcp-server", "model-context-protocol", "cursor", "codex", "claude"] classifiers = [ "Development Status :: 4 - Beta", "License :: OSI Approved :: Apache Software License", "Programming Language :: Python :: 3.13", "Topic :: Software Development :: Quality Assurance", ] dependencies = [ "mcp>=1.30.0,<2", "fastmcp>=3.4.7,<4", "tree-sitter>=0.26.0,<1", "tree-sitter-language-pack>=1.20.0,<2", "networkx>=3.6.1,<4", "watchdog>=6.0.0,<7", "fastretrieval>=1.7.1,<2", "httpx", "pydantic-settings", # Floor tracks the current mcp-core stable for cascade parity with # wet/mnemo. Carries the build_cli `config`/`doctor` PerPluginStore key # fix (#666) for servers whose plugin slug differs from server_name # (this repo's slug == server_name already, so no CLI regression here). # Keep this on a stable release -- a prerelease floor such as 1.20.0b2 # sorts below its own stable under PEP 440 and does not require it. "n24q02m-mcp-core[llm]==1.24.6", # litellm security floor (transitive via mcp-core[llm]). 1.83.x-1.87.x carry 4 # advisories in litellm's PROXY server: GHSA-r75f-5x8p-qvmc (SQLi in proxy key # verify), GHSA-xqmj-j6mv-4862 (SSTI /prompts/test), GHSA-v4p8-mg3p-g94g (cmd-exec # proxy MCP endpoints), GHSA-wxxx-gvqv-xp7p (sandbox escape custom-code guardrail). # We use litellm LIBRARY mode only (no proxy) so none are in our attack surface, # but Dependency Review flags the package version. 1.88.0+ clears all four. # crg's optional semgrep extra otherwise pins the resolver to litellm 1.83.0; this # floor lifts it (semgrep resolves to 1.79.x, fine for a dev-only SAST tool). "litellm>=1.101.0", "Pygments>=2.21.0", "alembic>=1.20.0,<2", "defusedxml>=0.7.1", ] [project.scripts] better-code-review-graph = "better_code_review_graph.cli:main" crg = "better_code_review_graph.cli:main" [project.optional-dependencies] security = [ # Cannot upgrade past 1.161 yet: semgrep >=1.162 pins mcp==1.23.3, which # conflicts with our mcp>=1.27 requirement. Renovate previously bumped to # 1.164.0 but that re-introduced the conflict — explicit upper cap until # semgrep relaxes its mcp pin (track: github.com/semgrep/semgrep upstream). "semgrep>=1.0,<1.162", ] [dependency-groups] dev = [ "bandit==1.9.4", "pytest==9.1.1", "pytest-asyncio==1.4.0", "pytest-cov", "pytest-timeout", "ruff==0.16.7", "syrupy", "ty==0.0.80", ] [tool.hatch.build.targets.wheel] packages = ["src/better_code_review_graph"] # Ship the alembic migrations directory inside the installed wheel as the # top-level package ``better_code_review_graph_migrations`` so that # ``GraphStore._run_alembic_upgrade`` can locate it via importlib.resources # regardless of the install location. [tool.hatch.build.targets.wheel.force-include] "migrations" = "better_code_review_graph_migrations" "rules" = "better_code_review_graph_security_rules" [tool.ruff] line-length = 88 target-version = "py313" [tool.ruff.lint] select = ["E", "F", "W", "I", "UP", "B", "C4"] ignore = ["E501"] [tool.ty.rules] unresolved-import = "ignore" unresolved-attribute = "ignore" possibly-missing-attribute = "ignore" [tool.pytest.ini_options] testpaths = ["tests"] asyncio_mode = "auto" asyncio_default_fixture_loop_scope = "function" timeout = 30 addopts = "--tb=short -q -m 'not integration and not full and not e2e'" markers = [ "integration: integration tests (deselect with '-m not integration')", "full: full/real live MCP protocol tests (deselect with '-m not full')", "e2e: end-to-end MCP protocol tests via conftest_e2e (deselect with '-m not e2e')", "slow: slow tests (deselect with '-m not slow')", ] [tool.coverage.run] source = ["src/better_code_review_graph"] branch = true [tool.coverage.report] fail_under = 95 show_missing = true exclude_lines = [ "pragma: no cover", "if TYPE_CHECKING:", "if __name__ == .__main__.:", "def serve_main", "async def run_http", ] [tool.semantic_release] version_toml = ["pyproject.toml:project.version"] version_variables = [".claude-plugin/plugin.json:version", "server.json:version"] tag_format = "v{version}" commit_message = "chore(release): v{version}" major_on_zero = false [tool.semantic_release.changelog] changelog_file = "CHANGELOG.md" [tool.semantic_release.remote] type = "github"