code-review-graph 2.2.0__tar.gz → 2.2.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/.gitignore +20 -15
  2. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/PKG-INFO +1 -1
  3. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/cli.py +0 -2
  4. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/graph.py +2 -3
  5. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/parser.py +45 -7
  6. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/prompts.py +3 -1
  7. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/skills.py +9 -9
  8. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/tools/context.py +4 -4
  9. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/docs/FEATURES.md +16 -1
  10. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/docs/LLM-OPTIMIZED-REFERENCE.md +11 -10
  11. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/pyproject.toml +1 -1
  12. code_review_graph-2.2.0/.claude-plugin/marketplace.json +0 -21
  13. code_review_graph-2.2.0/.claude-plugin/plugin.json +0 -21
  14. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/LICENSE +0 -0
  15. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/README.md +0 -0
  16. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code-review-graph-vscode/LICENSE +0 -0
  17. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code-review-graph-vscode/README.md +0 -0
  18. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/__init__.py +0 -0
  19. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/__main__.py +0 -0
  20. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/changes.py +0 -0
  21. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/communities.py +0 -0
  22. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/constants.py +0 -0
  23. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/embeddings.py +0 -0
  24. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/__init__.py +0 -0
  25. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/benchmarks/__init__.py +0 -0
  26. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/benchmarks/build_performance.py +0 -0
  27. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/benchmarks/flow_completeness.py +0 -0
  28. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/benchmarks/impact_accuracy.py +0 -0
  29. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/benchmarks/search_quality.py +0 -0
  30. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/benchmarks/token_efficiency.py +0 -0
  31. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/configs/express.yaml +0 -0
  32. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/configs/fastapi.yaml +0 -0
  33. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/configs/flask.yaml +0 -0
  34. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/configs/gin.yaml +0 -0
  35. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/configs/httpx.yaml +0 -0
  36. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/configs/nextjs.yaml +0 -0
  37. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/reporter.py +0 -0
  38. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/runner.py +0 -0
  39. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/scorer.py +0 -0
  40. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/eval/token_benchmark.py +0 -0
  41. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/flows.py +0 -0
  42. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/hints.py +0 -0
  43. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/incremental.py +0 -0
  44. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/main.py +2 -2
  45. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/migrations.py +0 -0
  46. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/refactor.py +0 -0
  47. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/registry.py +0 -0
  48. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/search.py +0 -0
  49. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/tools/__init__.py +3 -3
  50. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/tools/_common.py +0 -0
  51. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/tools/build.py +0 -0
  52. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/tools/community_tools.py +0 -0
  53. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/tools/docs.py +0 -0
  54. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/tools/flows_tools.py +0 -0
  55. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/tools/query.py +0 -0
  56. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/tools/refactor_tools.py +0 -0
  57. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/tools/registry_tools.py +0 -0
  58. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/tools/review.py +0 -0
  59. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/tsconfig_resolver.py +0 -0
  60. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/visualization.py +0 -0
  61. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/code_review_graph/wiki.py +0 -0
  62. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/docs/COMMANDS.md +0 -0
  63. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/docs/INDEX.md +0 -0
  64. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/docs/LEGAL.md +0 -0
  65. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/docs/ROADMAP.md +0 -0
  66. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/docs/TROUBLESHOOTING.md +0 -0
  67. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/docs/USAGE.md +0 -0
  68. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/docs/architecture.md +0 -0
  69. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/docs/schema.md +0 -0
  70. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/hooks/hooks.json +0 -0
  71. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/hooks/session-start.sh +0 -0
  72. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/skills/build-graph/SKILL.md +0 -0
  73. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/skills/review-delta/SKILL.md +0 -0
  74. {code_review_graph-2.2.0 → code_review_graph-2.2.2}/skills/review-pr/SKILL.md +0 -0
@@ -32,11 +32,16 @@ env/
32
32
  .DS_Store
33
33
  Thumbs.db
34
34
 
35
- # Node (if any JS tooling)
35
+ # Node
36
36
  node_modules/
37
37
 
38
+ # VS Code extension build artifacts
39
+ code-review-graph-vscode/dist/
40
+ *.vsix
41
+
38
42
  # Claude Code
39
43
  .claude/
44
+ .claude-plugin/
40
45
 
41
46
  # Coverage
42
47
  htmlcov/
@@ -49,26 +54,24 @@ htmlcov/
49
54
  # mypy
50
55
  .mypy_cache/
51
56
 
52
- # Medium article
53
- medium/
54
-
55
- # Superpowers brainstorm
56
- .superpowers/
57
- docs/superpowers/plans/
58
- docs/superpowers/specs/
59
-
60
- # Diagrams (PNGs + script tracked, excalidraw sources gitignored)
61
- diagrams/*.excalidraw
62
- diagrams/export_pngs.mjs
57
+ # Excalidraw source files (PNGs are tracked, sources are not)
63
58
  *.excalidraw
59
+ diagrams/export_pngs.mjs
64
60
 
65
- # Evaluation test repos (third-party checkouts)
61
+ # Evaluation (generated output — test repos, results, reports)
66
62
  evaluate/test_repos/
63
+ evaluate/results/
64
+ evaluate/reports/
67
65
 
68
- # Draft/duplicate files
66
+ # Superpowers brainstorm docs
67
+ .superpowers/
68
+ docs/superpowers/
69
+
70
+ # Draft/duplicate assets
69
71
  docs/assets/marketing-diagram*
70
72
 
71
- # One-off audit/design docs
73
+ # One-off docs (audits, analyses, plans, articles)
74
+ medium/
72
75
  Quality-Audit-Report.docx
73
76
  accessibility-audit.md
74
77
  cross-audit-synthesis.md
@@ -76,3 +79,5 @@ design-critique.md
76
79
  design-handoff.md
77
80
  design-system-audit.md
78
81
  research-synthesis.md
82
+ code-review-graph-analysis.md
83
+ SCALING_AND_TOKEN_EFFICIENCY_PLAN.md
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-review-graph
3
- Version: 2.2.0
3
+ Version: 2.2.2
4
4
  Summary: Persistent incremental knowledge graph for token-efficient, context-aware code reviews with Claude Code
5
5
  Project-URL: Homepage, https://code-review-graph.com
6
6
  Project-URL: Repository, https://github.com/tirth8205/code-review-graph
@@ -429,9 +429,7 @@ def main() -> None:
429
429
  from .incremental import (
430
430
  find_project_root,
431
431
  find_repo_root,
432
- full_build,
433
432
  get_db_path,
434
- incremental_update,
435
433
  watch,
436
434
  )
437
435
 
@@ -8,6 +8,7 @@ Supports impact-radius queries and subgraph extraction.
8
8
  from __future__ import annotations
9
9
 
10
10
  import json
11
+ import logging
11
12
  import sqlite3
12
13
  import threading
13
14
  import time
@@ -15,15 +16,13 @@ from dataclasses import dataclass
15
16
  from pathlib import Path
16
17
  from typing import Any, Optional
17
18
 
18
- import logging
19
-
20
19
  import networkx as nx
21
20
 
22
21
  from .constants import BFS_ENGINE, MAX_IMPACT_DEPTH, MAX_IMPACT_NODES
23
22
  from .migrations import get_schema_version, run_migrations
23
+ from .parser import EdgeInfo, NodeInfo
24
24
 
25
25
  logger = logging.getLogger(__name__)
26
- from .parser import EdgeInfo, NodeInfo
27
26
 
28
27
  # ---------------------------------------------------------------------------
29
28
  # Schema
@@ -242,6 +242,8 @@ _TEST_FILE_PATTERNS = [
242
242
  re.compile(r".*_test\.dart$"),
243
243
  re.compile(r"test[_-].*\.[rR]$"),
244
244
  re.compile(r"tests/testthat/"),
245
+ re.compile(r".*Test\.kt$"),
246
+ re.compile(r".*Test\.java$"),
245
247
  ]
246
248
 
247
249
  _TEST_RUNNER_NAMES = frozenset({
@@ -249,20 +251,29 @@ _TEST_RUNNER_NAMES = frozenset({
249
251
  "beforeAll", "afterAll",
250
252
  })
251
253
 
254
+ # Annotations/decorators that mark test methods (JUnit, TestNG, etc.)
255
+ _TEST_ANNOTATIONS = frozenset({
256
+ "Test", "ParameterizedTest", "RepeatedTest", "TestFactory",
257
+ "org.junit.Test", "org.junit.jupiter.api.Test",
258
+ })
259
+
252
260
 
253
261
  def _is_test_file(path: str) -> bool:
254
262
  return any(p.search(path) for p in _TEST_FILE_PATTERNS)
255
263
 
256
264
 
257
- def _is_test_function(name: str, file_path: str) -> bool:
258
- """A function is a test if its name matches test patterns or it lives
259
- in a test file and has a test-runner name (describe, it, test, etc.).
265
+ def _is_test_function(
266
+ name: str, file_path: str, decorators: tuple[str, ...] = (),
267
+ ) -> bool:
268
+ """A function is a test if its name matches test patterns, it lives
269
+ in a test file and has a test-runner name, or it has a @Test annotation.
260
270
  """
261
271
  if any(p.search(name) for p in _TEST_PATTERNS):
262
272
  return True
263
- # In test files, treat common JS/TS test-runner wrappers as tests
264
273
  if _is_test_file(file_path) and name in _TEST_RUNNER_NAMES:
265
274
  return True
275
+ if decorators and any(d in _TEST_ANNOTATIONS for d in decorators):
276
+ return True
266
277
  return False
267
278
 
268
279
 
@@ -1540,7 +1551,26 @@ class CodeParser:
1540
1551
  if not name:
1541
1552
  return False
1542
1553
 
1543
- is_test = _is_test_function(name, file_path)
1554
+ # Extract annotations/decorators for test detection
1555
+ decorators: tuple[str, ...] = ()
1556
+ deco_list: list[str] = []
1557
+ for sub in child.children:
1558
+ # Java/Kotlin/C#: annotations inside a modifiers child
1559
+ if sub.type == "modifiers":
1560
+ for mod in sub.children:
1561
+ if mod.type in ("annotation", "marker_annotation"):
1562
+ text = mod.text.decode("utf-8", errors="replace")
1563
+ deco_list.append(text.lstrip("@").strip())
1564
+ # Python: check parent decorated_definition for decorator siblings
1565
+ if child.parent and child.parent.type == "decorated_definition":
1566
+ for sib in child.parent.children:
1567
+ if sib.type == "decorator":
1568
+ text = sib.text.decode("utf-8", errors="replace")
1569
+ deco_list.append(text.lstrip("@").strip())
1570
+ if deco_list:
1571
+ decorators = tuple(deco_list)
1572
+
1573
+ is_test = _is_test_function(name, file_path, decorators)
1544
1574
  kind = "Test" if is_test else "Function"
1545
1575
  qualified = self._qualify(name, file_path, enclosing_class)
1546
1576
  params = self._get_params(child, language, source)
@@ -2432,7 +2462,8 @@ class CodeParser:
2432
2462
  return None # method child not found
2433
2463
 
2434
2464
  # Simple call: func_name(args)
2435
- if first.type == "identifier":
2465
+ # Kotlin uses "simple_identifier" instead of "identifier".
2466
+ if first.type in ("identifier", "simple_identifier"):
2436
2467
  return first.text.decode("utf-8", errors="replace")
2437
2468
 
2438
2469
  # Perl: function_call_expression / ambiguous_function_call_expression
@@ -2450,18 +2481,25 @@ class CodeParser:
2450
2481
  return None
2451
2482
 
2452
2483
  # Method call: obj.method(args)
2484
+ # Kotlin uses "navigation_expression" for member access (obj.method).
2453
2485
  member_types = (
2454
2486
  "attribute", "member_expression",
2455
2487
  "field_expression", "selector_expression",
2488
+ "navigation_expression",
2456
2489
  )
2457
2490
  if first.type in member_types:
2458
2491
  # Get the rightmost identifier (the method name)
2492
+ # Kotlin navigation_expression uses navigation_suffix > simple_identifier.
2459
2493
  for child in reversed(first.children):
2460
2494
  if child.type in (
2461
2495
  "identifier", "property_identifier", "field_identifier",
2462
- "field_name",
2496
+ "field_name", "simple_identifier",
2463
2497
  ):
2464
2498
  return child.text.decode("utf-8", errors="replace")
2499
+ if child.type == "navigation_suffix":
2500
+ for sub in child.children:
2501
+ if sub.type == "simple_identifier":
2502
+ return sub.text.decode("utf-8", errors="replace")
2465
2503
  return first.text.decode("utf-8", errors="replace")
2466
2504
 
2467
2505
  # Scoped call (e.g., Rust path::func())
@@ -12,7 +12,8 @@ detail_level="minimal" first patterns with get_minimal_context entry point.
12
12
 
13
13
  from __future__ import annotations
14
14
 
15
- _TOKEN_EFFICIENCY_PREAMBLE = """\
15
+ _TOKEN_EFFICIENCY_PREAMBLE = ( # nosec B105 — prompt template, not a password
16
+ """\
16
17
  ## Rules for Token-Efficient Graph Usage
17
18
  1. ALWAYS call `get_minimal_context` first with a task description.
18
19
  2. Use `detail_level="minimal"` on all tool calls unless the minimal output \
@@ -25,6 +26,7 @@ scans (list_communities with full members).
25
26
  6. When reviewing changes: detect_changes(detail_level="minimal") → only \
26
27
  expand on high-risk items.
27
28
  """
29
+ )
28
30
 
29
31
 
30
32
  def review_changes_prompt(base: str = "HEAD~1") -> list[dict]:
@@ -141,7 +141,7 @@ def install_platform_configs(
141
141
  existing: dict[str, Any] = {}
142
142
  if config_path.exists():
143
143
  try:
144
- existing = json.loads(config_path.read_text())
144
+ existing = json.loads(config_path.read_text(encoding="utf-8"))
145
145
  except (json.JSONDecodeError, OSError):
146
146
  logger.warning("Invalid JSON in %s, will overwrite.", config_path)
147
147
  existing = {}
@@ -176,7 +176,7 @@ def install_platform_configs(
176
176
  print(f" [dry-run] {plat['name']}: would write {config_path}")
177
177
  else:
178
178
  config_path.parent.mkdir(parents=True, exist_ok=True)
179
- config_path.write_text(json.dumps(existing, indent=2) + "\n")
179
+ config_path.write_text(json.dumps(existing, indent=2) + "\n", encoding="utf-8")
180
180
  print(f" {plat['name']}: configured {config_path}")
181
181
 
182
182
  configured.append(plat["name"])
@@ -325,7 +325,7 @@ def generate_skills(repo_root: Path, skills_dir: Path | None = None) -> Path:
325
325
  "---\n\n"
326
326
  f"{skill['body']}\n"
327
327
  )
328
- path.write_text(content)
328
+ path.write_text(content, encoding="utf-8")
329
329
  logger.info("Wrote skill: %s", path)
330
330
 
331
331
  return skills_dir
@@ -345,13 +345,13 @@ def generate_hooks_config() -> dict[str, Any]:
345
345
  "PostToolUse": [
346
346
  {
347
347
  "matcher": "Edit|Write|Bash",
348
- "command": "code-review-graph update --quiet --skip-flows",
348
+ "command": "code-review-graph update --skip-flows",
349
349
  "timeout": 5000,
350
350
  },
351
351
  ],
352
352
  "SessionStart": [
353
353
  {
354
- "command": "code-review-graph status --json",
354
+ "command": "code-review-graph status",
355
355
  "timeout": 3000,
356
356
  },
357
357
  ],
@@ -381,14 +381,14 @@ def install_hooks(repo_root: Path) -> None:
381
381
  existing: dict[str, Any] = {}
382
382
  if settings_path.exists():
383
383
  try:
384
- existing = json.loads(settings_path.read_text())
384
+ existing = json.loads(settings_path.read_text(encoding="utf-8"))
385
385
  except (json.JSONDecodeError, OSError) as exc:
386
386
  logger.warning("Could not read existing %s: %s", settings_path, exc)
387
387
 
388
388
  hooks_config = generate_hooks_config()
389
389
  existing.update(hooks_config)
390
390
 
391
- settings_path.write_text(json.dumps(existing, indent=2) + "\n")
391
+ settings_path.write_text(json.dumps(existing, indent=2) + "\n", encoding="utf-8")
392
392
  logger.info("Wrote hooks config: %s", settings_path)
393
393
 
394
394
 
@@ -445,7 +445,7 @@ def _inject_instructions(file_path: Path, marker: str, section: str) -> bool:
445
445
  """
446
446
  existing = ""
447
447
  if file_path.exists():
448
- existing = file_path.read_text()
448
+ existing = file_path.read_text(encoding="utf-8")
449
449
 
450
450
  if marker in existing:
451
451
  logger.info("%s already contains instructions, skipping.", file_path.name)
@@ -453,7 +453,7 @@ def _inject_instructions(file_path: Path, marker: str, section: str) -> bool:
453
453
 
454
454
  separator = "\n" if existing and not existing.endswith("\n") else ""
455
455
  extra_newline = "\n" if existing else ""
456
- file_path.write_text(existing + separator + extra_newline + section)
456
+ file_path.write_text(existing + separator + extra_newline + section, encoding="utf-8")
457
457
  logger.info("Appended MCP tools section to %s", file_path)
458
458
  return True
459
459
 
@@ -91,21 +91,21 @@ def get_minimal_context(
91
91
  # 3. Top 3 communities
92
92
  communities: list[str] = []
93
93
  try:
94
- rows = store.conn.execute(
94
+ rows = store._conn.execute(
95
95
  "SELECT name FROM communities ORDER BY size DESC LIMIT 3"
96
96
  ).fetchall()
97
97
  communities = [r[0] for r in rows]
98
- except Exception:
98
+ except Exception: # nosec B110 — table may not exist yet
99
99
  pass
100
100
 
101
101
  # 4. Top 3 critical flows
102
102
  flows: list[str] = []
103
103
  try:
104
- rows = store.conn.execute(
104
+ rows = store._conn.execute(
105
105
  "SELECT name FROM flows ORDER BY criticality DESC LIMIT 3"
106
106
  ).fetchall()
107
107
  flows = [r[0] for r in rows]
108
- except Exception:
108
+ except Exception: # nosec B110 — table may not exist yet
109
109
  pass
110
110
 
111
111
  # 5. Suggest next tools based on task keywords
@@ -1,6 +1,21 @@
1
1
  # Features
2
2
 
3
- ## v2.1.0 (Current)
3
+ ## v2.2.1 (Current)
4
+ - **24 MCP tools** (up from 22): Added `get_minimal_context` and `run_postprocess`.
5
+ - **Parallel parsing**: `ProcessPoolExecutor` for 3-5x faster builds on large repos.
6
+ - **Lazy post-processing**: `postprocess="full"|"minimal"|"none"` to skip expensive steps.
7
+ - **SQLite-native BFS**: Recursive CTE replaces NetworkX for impact analysis (faster on large graphs).
8
+ - **Token-efficient output**: `detail_level="minimal"` on 8 tools for 40-60% token reduction.
9
+ - **`get_minimal_context`**: Ultra-compact entry point (~100 tokens) with task-based tool routing.
10
+ - **Incremental flow/community updates**: Only re-trace affected flows, skip community re-detection when unaffected.
11
+ - **Visualization aggregation**: Community/file/auto modes with drill-down for 5k+ node graphs.
12
+ - **Token-efficiency benchmarks**: 5 workflow benchmarks in eval framework.
13
+ - **Pre-computed summary tables**: DB schema v6 with `community_summaries`, `flow_snapshots`, `risk_index`.
14
+ - **Configurable limits**: `CRG_MAX_IMPACT_NODES`, `CRG_MAX_IMPACT_DEPTH`, `CRG_DEPENDENT_HOPS`, etc.
15
+ - **Multi-hop dependents**: N-hop dependent discovery (default 2) with 500-file cap.
16
+ - **615 tests** across 22 test files.
17
+
18
+ ## v2.1.0
4
19
  - **22 MCP tools** (up from 9): 13 new tools for flows, communities, architecture, refactoring, wiki, multi-repo, and risk-scored change detection.
5
20
  - **5 MCP prompts**: `review_changes`, `architecture_map`, `debug_issue`, `onboard_developer`, `pre_merge_check` workflow templates.
6
21
  - **18 languages** (up from 15): Added Dart, R, Perl support.
@@ -1,4 +1,4 @@
1
- # LLM-OPTIMIZED REFERENCE -- code-review-graph v2.1.0
1
+ # LLM-OPTIMIZED REFERENCE -- code-review-graph v2.2.1
2
2
 
3
3
  Claude Code: Read ONLY the exact `<section>` you need. Never load the whole file.
4
4
 
@@ -7,15 +7,15 @@ Quick install: pip install code-review-graph
7
7
  Then: code-review-graph install && code-review-graph build
8
8
  First run: /code-review-graph:build-graph
9
9
  After that use only delta/pr commands.
10
- For v2 features: detect_changes_tool for risk-scored reviews, list_flows_tool for execution paths, list_communities_tool for architecture.
10
+ ALWAYS start with get_minimal_context_tool(task="your task") returns ~100 tokens with risk, communities, flows, and suggested next tools.
11
+ Use detail_level="minimal" on all subsequent calls unless you need more detail.
11
12
  </section>
12
13
 
13
14
  <section name="review-delta">
14
- Always call get_impact_radius on changed files first.
15
- Then get_review_context (depth=2).
16
- Or use detect_changes_tool for risk-scored, priority-ordered review guidance.
17
- Generate review using ONLY changed nodes + 2-hop neighbors.
18
- Target: <800 tokens total context.
15
+ 1. Call get_minimal_context_tool(task="review changes") first.
16
+ 2. If risk is low: detect_changes_tool(detail_level="minimal") → report summary.
17
+ 3. If risk is medium/high: detect_changes_tool(detail_level="standard") expand on high-risk items.
18
+ Target: ≤5 tool calls, ≤800 tokens total context.
19
19
  </section>
20
20
 
21
21
  <section name="review-pr">
@@ -24,10 +24,11 @@ Never include full files unless explicitly asked.
24
24
  </section>
25
25
 
26
26
  <section name="commands">
27
- MCP tools (22): build_or_update_graph_tool, get_impact_radius_tool, query_graph_tool, get_review_context_tool, semantic_search_nodes_tool, embed_graph_tool, list_graph_stats_tool, get_docs_section_tool, find_large_functions_tool, list_flows_tool, get_flow_tool, get_affected_flows_tool, list_communities_tool, get_community_tool, get_architecture_overview_tool, detect_changes_tool, refactor_tool, apply_refactor_tool, generate_wiki_tool, get_wiki_page_tool, list_repos_tool, cross_repo_search_tool
27
+ MCP tools (24): get_minimal_context_tool, build_or_update_graph_tool, run_postprocess_tool, get_impact_radius_tool, query_graph_tool, get_review_context_tool, semantic_search_nodes_tool, embed_graph_tool, list_graph_stats_tool, get_docs_section_tool, find_large_functions_tool, list_flows_tool, get_flow_tool, get_affected_flows_tool, list_communities_tool, get_community_tool, get_architecture_overview_tool, detect_changes_tool, refactor_tool, apply_refactor_tool, generate_wiki_tool, get_wiki_page_tool, list_repos_tool, cross_repo_search_tool
28
28
  MCP prompts (5): review_changes, architecture_map, debug_issue, onboard_developer, pre_merge_check
29
29
  Skills: build-graph, review-delta, review-pr
30
- CLI: code-review-graph [install|init|build|update|status|watch|visualize|serve|wiki|detect-changes|register|unregister|repos|eval]
30
+ CLI: code-review-graph [install|init|build|update|status|watch|visualize|serve|wiki|detect-changes|postprocess|register|unregister|repos|eval]
31
+ Token efficiency: All tools support detail_level="minimal" for compact output. Always call get_minimal_context_tool first.
31
32
  </section>
32
33
 
33
34
  <section name="legal">
@@ -48,7 +49,7 @@ Configure via CRG_EMBEDDING_MODEL env var or model parameter.
48
49
  </section>
49
50
 
50
51
  <section name="languages">
51
- Supported (18): Python, TypeScript/TSX, JavaScript, Vue, Go, Rust, Java, Scala, C#, Ruby, Kotlin, Swift, PHP, Solidity, C/C++, Dart, R, Perl
52
+ Supported (19): Python, TypeScript/TSX, JavaScript, Vue, Go, Rust, Java, Scala, C#, Ruby, Kotlin, Swift, PHP, Solidity, C/C++, Dart, R, Perl, Lua
52
53
  Parser: Tree-sitter via tree-sitter-language-pack
53
54
  </section>
54
55
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "code-review-graph"
7
- version = "2.2.0"
7
+ version = "2.2.2"
8
8
  description = "Persistent incremental knowledge graph for token-efficient, context-aware code reviews with Claude Code"
9
9
  readme = {file = "README.md", content-type = "text/markdown"}
10
10
  license = "MIT"
@@ -1,21 +0,0 @@
1
- {
2
- "name": "code-review-graph",
3
- "owner": {
4
- "name": "Tirth Kanani",
5
- "email": "tirthkanani18@gmail.com"
6
- },
7
- "metadata": {
8
- "description": "Persistent incremental knowledge graph for token-efficient, context-aware code reviews with Claude Code",
9
- "version": "2.1.0"
10
- },
11
- "plugins": [
12
- {
13
- "name": "code-review-graph",
14
- "source": "./",
15
- "description": "Persistent incremental knowledge graph for token-efficient, context-aware code reviews with Claude Code",
16
- "version": "2.1.0",
17
- "category": "development",
18
- "keywords": ["code-review", "knowledge-graph", "incremental", "tree-sitter", "mcp", "claude-code"]
19
- }
20
- ]
21
- }
@@ -1,21 +0,0 @@
1
- {
2
- "name": "code-review-graph",
3
- "description": "Persistent incremental knowledge graph for token-efficient, context-aware code reviews with Claude Code",
4
- "version": "2.1.0",
5
- "author": {
6
- "name": "Tirth Kanani",
7
- "email": "tirthkanani18@gmail.com",
8
- "url": "https://github.com/tirth8205"
9
- },
10
- "homepage": "https://code-review-graph.com",
11
- "repository": "https://github.com/tirth8205/code-review-graph",
12
- "license": "MIT",
13
- "keywords": ["code-review", "knowledge-graph", "incremental", "tree-sitter", "mcp", "claude-code"],
14
- "mcpServers": {
15
- "code-review-graph": {
16
- "command": "uvx",
17
- "args": ["code-review-graph", "serve"]
18
- }
19
- },
20
- "skills": "./skills/"
21
- }
@@ -21,8 +21,6 @@ from .tools import (
21
21
  apply_refactor_func,
22
22
  build_or_update_graph,
23
23
  cross_repo_search_func,
24
- get_minimal_context,
25
- run_postprocess,
26
24
  detect_changes_func,
27
25
  embed_graph,
28
26
  find_large_functions,
@@ -33,6 +31,7 @@ from .tools import (
33
31
  get_docs_section,
34
32
  get_flow,
35
33
  get_impact_radius,
34
+ get_minimal_context,
36
35
  get_review_context,
37
36
  get_wiki_page_func,
38
37
  list_communities_func,
@@ -41,6 +40,7 @@ from .tools import (
41
40
  list_repos_func,
42
41
  query_graph,
43
42
  refactor_func,
43
+ run_postprocess,
44
44
  semantic_search_nodes,
45
45
  )
46
46
 
@@ -46,9 +46,6 @@ from ._common import (
46
46
  # -- build ------------------------------------------------------------------
47
47
  from .build import build_or_update_graph, run_postprocess
48
48
 
49
- # -- context ----------------------------------------------------------------
50
- from .context import get_minimal_context
51
-
52
49
  # -- community_tools --------------------------------------------------------
53
50
  from .community_tools import (
54
51
  get_architecture_overview_func,
@@ -56,6 +53,9 @@ from .community_tools import (
56
53
  list_communities_func,
57
54
  )
58
55
 
56
+ # -- context ----------------------------------------------------------------
57
+ from .context import get_minimal_context
58
+
59
59
  # -- docs -------------------------------------------------------------------
60
60
  from .docs import embed_graph, generate_wiki_func, get_docs_section, get_wiki_page_func
61
61