Files
tirth8205--code-review-graph/CHANGELOG.md
T
2026-07-13 12:42:18 +08:00

64 KiB
Raw Blame History

Changelog

[Unreleased]

[2.3.6] - 2026-06-10

Community-response release. Built from a full audit of every open PR, issue, and discussion: community fixes merged with credit, verified defects fixed (including two open Windows bugs), benchmark claims made independently checkable, and the project's first self-hosted PR review bot — this repo now reviews its own pull requests with its own graph. No breaking changes.

Added

  • Custom languages without forking (#320): drop a .code-review-graph/languages.toml into your repo to index any grammar shipped by tree-sitter-language-pack (extension map + node-type lists, validated and capped, built-ins always win). See docs/CUSTOM_LANGUAGES.md.
  • GitHub Action for risk-scored PR review comments: composite action.yml builds/restores the graph from CI cache, runs detect-changes against the PR base, and upserts a sticky comment with risk table, affected flows, test gaps, and the Token Savings line. Dogfooded on this repo via .github/workflows/pr-review.yml. See docs/GITHUB_ACTION.md.
  • agent_baseline eval benchmark: compares graph queries against a realistic grep-and-read-top-k agent baseline instead of the whole-corpus strawman; wired into all six pinned eval configs.
  • Co-change ground truth for impact_accuracy: predictions are now also graded against files actually co-changed in the same commit; the legacy metric is explicitly labelled "graph-derived (circular — upper bound)".
  • Weekly eval CI (.github/workflows/eval.yml): report-only cron run of the two smallest pinned configs with CSV artifacts and a job summary.
  • docs/FAQ.md: how CRG compares to LSP, RAG, grep/agentic search, and adjacent tools; when NOT to use it; verification steps; monorepo/worktree and registry guidance. Linked from the README.
  • GitHub issue forms (bug/feature/platform), a PR template mirroring the CONTRIBUTING checklist, and dependabot config for pip + GitHub Actions.

Fixed

  • store_file_batch is now guarded against open transactions like its sibling (#489, merged from community PR #529 by @Devilthelegend — thank you).
  • Windows: daemon status no longer crashes with WinError 87 (#511): PID liveness now uses OpenProcess/WaitForSingleObject on win32 instead of os.kill(pid, 0).
  • Windows: CLI detect-changes mapped 0 functions (#528): diff paths are now remapped to absolute native paths before node lookup, matching the MCP tool's behavior; also prevents the misleading "~100% token savings" line on an empty result.
  • Eval benchmarks no longer record failed runs as inflated wins: thrown get_review_context/analyze_changes calls are marked status=error and excluded from aggregates instead of producing naive/1 ratios or recall=1.0.
  • Unknown embedding provider names now raise a clear error listing valid providers instead of silently falling back to the local model.
  • The five analysis MCP tools and the wiki-page tool no longer leak SQLite connections (try/finally store.close()).
  • install git hooks now resolve the real hooks directory via git rev-parse --git-path hooks, so linked worktrees and core.hooksPath (husky) setups get a working pre-commit hook (#313 residue).
  • Shipped hooks/hooks.json and hooks/session-start.sh now drain stdin, matching the generated configs (#493 class).
  • fastmcp is now capped <4 so the next major cannot silently break the server (the #488 failure mode).

Changed

  • README benchmarks section now leads with the ~82x median per-question reduction (528x presented as the best case, not the headline), the limitations block is visible instead of collapsed, and "100% impact recall" is reframed as a graph-derived upper bound alongside the new co-change metric.
  • Stale translated READMEs (zh-CN, ja-JP, ko-KR, hi-IN) carry a staleness banner; the zh-CN benchmark captions and docs/USAGE.md no longer contradict the English README.
  • SECURITY.md now points to GitHub private vulnerability reporting as the canonical channel.

[2.3.5] - 2026-05-25

Real-time token savings, visible to humans. The estimated context-savings metric introduced in 2.3.4 was JSON-only. In 2.3.5 it surfaces as a clean boxed panel on the CLI and is verifiable against a real tokenizer in one flag — so when you reach for code-review-graph to review a change, you can immediately see how much of your context window the graph just kept out. No breaking changes.

Added — Token Savings (headline feature)

  • Boxed Token Savings panel on every --brief CLI call. Both code-review-graph detect-changes --brief and the new code-review-graph update --brief print a four-line panel: the full-context baseline, the graph response size, total saved tokens with percent, and a per-category breakdown (Functions / Tests / Risk / Other) that sums exactly to the graph response size — no padding, no rounding magic.

    ┌─────────────────────── Token Savings ────────────────────────┐
    │ Full context would be:     12,921 tokens                     │
    │ Graph context used:           762 tokens                     │
    │ Saved:                     12,159 tokens (~94%)              │
    │ Breakdown: Functions 244 · Tests 191 · Risk 244 · Other 83   │
    └──────────────────────────────────────────────────────────────┘
    
  • --verify flag cross-checks the displayed numbers against OpenAI's cl100k_base tokenizer (the GPT-4 family). Adds a second Verified (tiktoken) row to the panel showing the real token counts. Requires pip install tiktoken. A one-time calibration across 222 mixed source files (Python/JS/TS/Go/Rust/RST/MD) committed in docs/REPRODUCING.md shows the chars/4 approximation stays within +0.5% of real tokens in aggregate; per-repo bias is bounded to ±12% and the ratio stays stable because both sides of the divide are equally biased.

  • code-review-graph update --brief — incremental update plus the same risk + Token Savings panel in one command. Distinct from detect-changes --brief (which is read-only against the existing graph). Use update --brief when the graph might be stale (post-rebase, large change set); use detect-changes --brief when hooks/crg-daemon have already kept the graph fresh.

Added — Reproducible benchmarks

  • docs/REPRODUCING.md — end-to-end reproduction recipe with canonical numbers, the tiktoken calibration table, and an explicit explanation of the three different "token" benchmarks in the codebase and what each measures. Two people running the recipe on different machines on different days now produce identical numbers, within float rounding.
  • multi_hop_retrieval benchmark — 11 hand-curated 2-step tool-chain tasks (semantic_search → query_graph) across the 6 test repos. Average score 0.909. Per-task CSV in evaluate/results/.
  • code-review-graph embed CLI subcommand — explicit shell-level access to embedding generation. Previously only reachable via MCP, which made the benchmark recipe awkward.

Changed — Deterministic eval pipeline

  • Every config under code_review_graph/eval/configs/*.yaml now pins an upstream SHA. Previously every config used commit: HEAD, which made benchmarks drift whenever upstream pushed. Pinned SHAs: express b4ab7d65, fastapi 0227991a, flask a29f88ce, gin 5c00df8a, httpx b55d4635, code-review-graph 84bde354.
  • nextjs.yaml renamed to code-review-graph.yaml. The historical "nextjs" entry pointed at this repo, not a Next.js codebase. Renamed to match reality.
  • eval/runner.py uses full clones with explicit returncode checks. Previously --depth 50 silently fell back to HEAD~1..HEAD whenever a pinned test-commit SHA was past the shallow window, producing benchmark numbers tied to whichever HEAD the clone happened to grab.
  • Leiden community detection seeded (CRG_LEIDEN_SEED, default 42). Previously unseeded — community IDs and sizes drifted run-to-run on the same graph, breaking benchmark comparability.
  • eval/runner.py resolves repo paths absolutely before storing. The parser previously stored file_path as the path you passed in, so eval builds and CLI/MCP builds could disagree, producing duplicate nodes for the same source location. Fixed by .resolve() in the runner.
  • eval/runner.py calls run_post_processing after full_build. Previously the eval framework left FTS5 unpopulated (shadow tables nodes_fts_idx and nodes_fts_docsize empty), so downstream search and multi-hop benchmarks silently returned no results.

Changed — Search and embeddings

  • embeddings._node_to_text is richer. Embedded text per node now includes the dotted form (Parent.name, e.g. APIRoute.get_route_handler), the identifier split into words (get route handler), and the enclosing module directory (routing, dependencies). Forces an automatic re-embedding because the text hash changes. Lifts multi-hop benchmark accuracy from 0.545 → 0.818.
  • Identifier-aware search boost (search.extract_query_identifiers). Natural-language queries like "Who advances the gin middleware chain via Context.Next" now have their dotted / snake_case / CamelCase tokens extracted and used to boost matching qualified-names by 2.0× in hybrid search. Combined with the richer embed text, multi-hop accuracy reaches 0.909 (10 of 11 tasks pass).

Fixed

  • Test-gap dedup in the brief summary. If duplicate qualified_names ever slip into the graph (e.g. after a path-normalization mismatch), the Untested: line in the human summary now collapses to unique names. The underlying test_gaps list still carries every entry.
  • token_benchmark.py warns when embeddings are missing. The standalone benchmark's default NL questions need semantic search to match anything; without embeddings the benchmark used to silently report 0× reduction ratios. Now logs an explicit warning pointing users to embed.

Documentation

  • docs/REPRODUCING.md (new). End-to-end recipe, canonical numbers, the tiktoken calibration table, and a side-by-side explanation of the three "token" benchmarks in the codebase.
  • README.md Token Savings section (new collapsible block under Usage). Plain-English explanation of detect-changes --brief vs update --brief — read-only vs re-parses-first — with a side-by-side decision table.
  • docs/COMMANDS.md lists the new --brief, --verify, and embed forms with an inline "which one?" comment block on the analysis pair.
  • Updated benchmark headline to reflect today's pinned-SHA snapshot: range 38× 528× (median ~82×) across the 6 repos, 100% impact recall, F1 0.71 across 13 commits. Old numbers (73× 895×) reflected pre-fix conditions (leftover build artifacts, smaller graph responses) and have been superseded.
  • 9 Excalidraw diagrams regenerated with current canonical numbers (diagrams/*.excalidraw, source kept locally; PNG re-exports manual).

Demo

  • diagrams/context-savings-demo.gif — 44 s screencast showing both CLI surfaces and the --verify cross-check. Rendered from diagrams/context-savings-demo.tape (regenerable with vhs).

[2.3.4] - 2026-05-25

Focused reliability and token-efficiency release for MCP/CLI review workflows. No breaking changes.

Added

  • Estimated context savings metadata for graph-filtered review/impact/architecture responses. The new context_savings field is intentionally compact (estimated, saved_tokens, saved_percent) and uses the existing conservative character-count approximation rather than claiming exact tokenization.
  • CLI estimated savings line for code-review-graph detect-changes --brief; full JSON output includes the same compact context_savings metadata.

Changed

  • Architecture overview is compact by default: get_architecture_overview_tool now defaults to detail_level="minimal", dropping per-community member lists and aggregating cross-community edges by community pair. Full per-edge output remains available with detail_level="standard".
  • Bounded change analysis: detect_changes_tool can now cap very large changed-function and transitive-test frontiers with CRG_MAX_CHANGED_FUNCS and CRG_MAX_TRANSITIVE_FRONTIER, and can return a structured timeout error via CRG_TOOL_TIMEOUT.

Fixed

  • Windows semantic search deadlock (#508/#507): local embedding models are pre-warmed on the main thread on Windows before FastMCP starts worker dispatch.
  • Rust test detection (#503/#502): Rust #[test] and common async test attributes now produce Test nodes.
  • Generated hook stdin handling (#494/#493): Codex and Claude hook commands drain stdin to avoid caller-side broken pipes on large hook payloads.
  • Cross-file callers (#486/#472): callers_of now returns cross-file callers even when same-file callers exist.
  • Graph path lookup (#469): review, impact, and file-summary tools resolve user-facing paths to the path format stored in the graph.
  • Bundled MCP docs (#485/#480): get_docs_section can load the packaged LLM-OPTIMIZED-REFERENCE.md from installed wheels.
  • Local embedding provider availability (#484/#448): missing sentence-transformers now reports local provider unavailability instead of silently producing zero embeddings.
  • Dead-code response fields (#481/#447): dead-code results now include file_path, relative_path, and language while preserving the legacy file key.
  • SVN root validation (#456): MCP/daemon/registry root validation now accepts .svn working copies consistently.
  • CLI postprocess flags (#487): build --skip-postprocess and update --skip-flows no longer run an extra full post-processing pass.

Documentation

  • Updated stale release-facing version references for 2.3.4.
  • Replaced fragile language-count wording with current broad language and notebook support wording.
  • Added the missing VS Code extension 0.2.2 changelog entry without changing the extension package version.

Tests

  • Added regression coverage for compact architecture overview output and #476 mitigation.
  • Added tests for estimated context savings calculation, compact metadata shape, MCP metadata, CLI brief/JSON output, Rust test parsing, hook stdin draining, graph path resolution, dead-code fields, SVN root validation, CLI postprocess flags, embedding availability, and bounded detect-changes behavior.

[2.3.3] - 2026-05-08

Large additive release accumulated since v2.3.2 — 141 non-merge commits, 8 new languages/extensions, 5 new platform install targets, 6 new framework call resolvers, comprehensive Windows hardening, VS Code accessibility pass, and a full sweep of community PRs.

Added

Languages and extensions

  • Nix support (flake-aware): .nix files are parsed via the nix tree-sitter grammar shipped with tree-sitter-language-pack. Top-level and nested attrset bindings become Function nodes with flattened dotted names (e.g. packages.default, devShells.default). In flake.nix, inputs.<name>.url = "..." strings emit IMPORTS_FROM edges to the URL; import <path> and callPackage <path> <args> applications in any .nix file emit IMPORTS_FROM edges (relative paths are resolved against the caller's directory). Adds 7 tests (TestNixParsing) and fixtures tests/fixtures/sample.nix, tests/fixtures/sample_module.nix.
  • GDScript support (Godot, PR #316): .gd files are parsed via the gdscript tree-sitter grammar. Extracts inner classes (class Name:), the file-level class_name identity, functions (including static func), extends parent class as an IMPORTS_FROM edge, direct calls and method calls. Adds 10 tests and tests/fixtures/sample.gd.
  • Verilog / SystemVerilog support (PR #428): .v, .sv, .svh files parse modules, classes, packages, interfaces, programs, functions, and tasks via the verilog tree-sitter grammar. Per-construct extractors with dedicated unit tests.
  • SQL support (PR #398): .sql files parse CREATE FUNCTION, CREATE PROCEDURE, CREATE TABLE, and CREATE VIEW statements; emits CALLS edges for function invocations.
  • ReScript support (PR #309/323): .res/.resi parsing for modules, let-bindings, and external declarations.
  • .hh extension support: C++ header variants now resolve into the C++ parser path.
  • .ksh extension and shebang-based detection (PR #276): .ksh files parsed as shell; extension-less scripts detected via #!/usr/bin/env <lang> shebang lines.
  • Julia improvements: parametric constructors, @enum declarations, and public module exports now produce graph nodes.

Platforms and install targets

  • GitHub Copilot platform support (PR #445): code-review-graph install --platform copilot writes Copilot-CLI-compatible MCP config without generating Claude-specific skill artifacts.
  • Gemini CLI platform support (PR #391): --platform gemini-cli skips Claude skills and writes Gemini-native MCP config.
  • Qoder platform support (PR #245): --platform qoder adds MCP server registration for Qoder.
  • OpenCode plugin support (PR #198 via #366): --platform opencode registers the MCP server with the OpenCode plugin manifest.
  • Cursor hooks support (PR #196): install now writes Cursor hook entries (gated behind ~/.cursor detection so non-Cursor users are not affected).
  • Codex install alignment: native Codex integration path; no Claude skill files generated for Codex targets.

MCP server and CLI features

  • crg-daemon: new multi-repo watch daemon that supervises per-repo file watchers via subprocess.Popen child processes. Documented in README, COMMANDS.md, and ROADMAP.md. 35 dedicated tests.
  • Streamable HTTP transport (PR #277): MCP server can now run over streamable HTTP in addition to stdio.
  • serve --tools flag and CRG_TOOLS env var: MCP tool filtering at startup so callers can expose only the subset they need.
  • --repo precedence and validation in get_docs_section (PR #378): honors serve --repo and validates path containment before returning section content.
  • Search enrichment via PreToolUse hooks (PR #248): hook-driven search index enrichment ahead of tool calls.
  • External database directory support: graph DB can now live on a network filesystem via the existing CRG_DATA_DIR mechanism, with the file locking path adjusted accordingly.
  • SVN support (PR #255): basic Subversion working-copy detection alongside git for change analysis.

Parser and resolver improvements

  • Spring DI call resolution (PR #413): receiver method calls (this.userService.find(...)) resolve through @Autowired/constructor-injected fields to the concrete InjectedType.method. Emits INJECTS edges and stereotype metadata (@Service, @Component, @Repository, @Controller); writes fully-qualified target_qualified so callers_of queries work.
  • Temporal workflow/activity call resolution: WorkflowStub.start(...) and ActivityStub.execute(...) resolve to their concrete workflow/activity implementations.
  • Kafka consumer/producer detection: @KafkaListener-annotated methods and KafkaTemplate.send(...) calls emit CONSUMES and PRODUCES edges keyed on topic.
  • Jedi-based Python call resolution (PR #247): improved cross-file Python call resolution using the Jedi static-analysis library.
  • Python callback REFERENCES edges (PR #363): function names passed as callback arguments (schedule(my_handler)) now emit REFERENCES edges instead of being dropped.
  • Mocha TDD suite() recognition (PR #423): files using Mocha's TDD interface now classify as tests.
  • Bun test runtime support (PR #421): files importing bun:test are detected as tests.
  • __tests__/ directory detection (PR #422): all files under __tests__/ are classified as test files regardless of name.

Embeddings

  • OpenAI-compatible embedding provider (PR #321): pluggable provider supporting OpenAI, Azure OpenAI, and any OpenAI-API-compatible endpoint, with configurable batch size.
  • Localized embedding READMEs: provider docs translated for non-English users.

Visualization, accessibility, and VS Code extension

  • WCAG 2.1 AA contrast pass: 4.5:1 minimum text contrast across the standalone HTML and VS Code webview.
  • Distinct d3.symbol shapes per node kind: colorblind-friendly differentiation in both the standalone visualization and the VS Code webview.
  • Keyboard navigation: tab/arrow/enter/escape navigation across nodes, with focus styles and a skip-link to bypass the legend.
  • ARIA roles and labels: tooltip, detail panel, legend, search results, communities button, edge-pill keyboard activation, search input label.
  • Help overlay: interaction guide for both the standalone HTML and the keyboard-help overlay.
  • Empty-state webview in VS Code with a contextual depth slider and tooltip.
  • Edge filter popover in the VS Code toolbar — fixes density on narrow panels.
  • Detail panel relocated to the left so it no longer occludes top controls; close button restyled to match the toolbar.
  • CONTAINS edge opacity raised from 0.08 → 0.14 for visibility on dense graphs.
  • GitHub Dark palette unified across the VS Code extension.
  • IMPLEMENTS, TESTED_BY, DEPENDS_ON edge types rendered in the standalone HTML visualization.

Fixed

__version__ reporting

  • code_review_graph.__version__ now matches pyproject.toml (was 2.1.0 since the v2.1.0 release). The User-Agent header that embeddings.py sends on cloud HTTP requests is built from this string, so cloud-embedding traffic was being mis-attributed across all releases between v2.1.0 and v2.3.2.

C++ / Java / PHP parsing

  • C++ scoped/destructor/operator method names (PR #371, PR #403): void Foo::bar(), Foo::~Foo(), Foo::operator==(...) now extract the correct member name instead of the qualifier or the operator token.
  • Java method name extraction (PR #275): method names are now read from the identifier child of method_declaration rather than the return-type child (which was producing names like int64).
  • Java superclass / super-interfaces (PR #278): extends Foo and implements Bar, Baz now extract bare type names from the superclass/super_interfaces AST nodes.
  • Java import resolution to file paths (PR #280): import com.example.foo.Bar resolves through src/main/java/... and configured source roots to the actual file.
  • PHP CALL extraction (PR #298): method calls ($obj->foo()), static calls (Foo::bar()), and unqualified function calls now produce CALLS edges.
  • Module-scope CALLS edges (PR #285): top-level executable statements emit CALLS edges (previously only function/method bodies did).

Windows

  • Windows MCP stdio hang on long-running tools (PR #400, PR #292): thread-pool selection now auto-selects on Windows MCP stdio so build/embed do not deadlock.
  • Windows MCP stdin hang (PR #425): all git/svn subprocesses now run with stdin=DEVNULL, preventing the FastMCP-stdio buffer from filling on Windows.
  • Windows non-UTF-8 locale: subprocess.run calls now pass encoding="utf-8" so cp1252 hosts no longer mis-decode git output.
  • Windows test failures (PR #274): UTF-8 encoding, CRLF normalization, and stop_at boundary handling fixes for Windows CI.

Hooks and install

  • Hooks JSON schema (PR #288): hooks.json validation no longer fails on the wrapper layout — matcher is required and the wrapper is removed.
  • Hooks merge instead of overwrite (PR #114, PR #145, PR #203): install_hooks now merges into existing hook arrays and creates a settings.json.bak backup before modifying user config.
  • Pre-commit hook adds update command (PR #315): generated pre-commit hook runs code-review-graph update rather than the obsolete subcommand.
  • Skip hooks gracefully outside git (PR #293): install no longer fails when invoked from a non-git directory.
  • Poetry / uv environment detection (PR #287): install now generates the correct MCP serve command for projects using Poetry or uv.
  • Hook quoting and docs repo_root (PR #192): hook commands now quote repo paths with spaces, and the docs repo path is restored on install.

MCP server

  • fastmcp 3.x compatibility: _apply_tool_filter restored on fastmcp ≥3, dependency floor bumped to fastmcp>=3.2.4 to pick up the upstream Windows stdio EOF fixes.
  • FastMCP banner suppressed for stdio transport (PR #290): the startup banner no longer corrupts the stdio handshake.
  • MCP config cwd, skills path, and JSONC parsing: install now writes cwd into MCP config, points skills at the correct project path, and tolerates JSONC (comments + trailing commas) in existing config files.

SQLite and post-processing

  • SQLite transaction safety, FTS5 sync, and atomic operations (PR #94, PR #279): nested-transaction handling, FTS5 content-table synchronization, and resource cleanup on error paths.
  • CLI build/update/watch run post-processing (PR #98): signatures, FTS, flows, and communities are now refreshed after every CLI graph mutation (was previously only refreshed by the MCP server).
  • reconcile() auto-builds graphs and registers new repos: cold-start path no longer requires a manual build before reconcile.
  • Flow trace adjacency in-memory (PR #296): trace_flows loads adjacency once instead of querying SQLite per hop.

Other

  • UnicodeDecodeError in read_text (PR #303): all text reads now use errors="replace".
  • Dead-code callback references (PR #424): functions referenced as callbacks no longer mis-classify as dead code.
  • Skills.py table formatting (PR #302).
  • Search.py duplicate logger removed.
  • status command reports alive/dead from the persisted state file.

Security

  • Embeddings RCE hardening (PR #397): remote code execution paths in the embedding provider are gated behind an explicit env var; cloud HTTP requests now send a versioned User-Agent (PR #390) and refuse to mix indexes built with different providers.

Documentation

  • MCP tools documentation (PR #306): catalog of all MCP tools with usage examples.
  • venv usage guide (PR #307).
  • Windows setup guide for Claude Code MCP integration.
  • pipx / PyPI failure troubleshooting with a diagnose_pypi_connectivity.py diagnostic script.
  • MseeP.ai badge added to README (PR #399).

Maintenance

  • Beads (bd) issue tracking initialized for the project (bd prime for workflow context).
  • iCloud sync duplicate files removed from the working tree.
  • Working spec docs moved out of git (already in .gitignore).
  • CI lint and test failures swept across multiple merged PRs.

Upgrade notes

  • uvx --reinstall code-review-graph or pip install -U code-review-graph.
  • Re-run code-review-graph install once after upgrading to pick up the JSONC-tolerant config writer and the corrected cwd / skills path in .mcp.json.
  • The __version__ fix changes the User-Agent string emitted by cloud embedding providers from code-review-graph/2.1.0 to code-review-graph/2.3.3. Anyone allow-listing the old User-Agent on a proxy needs to update their rule.
  • VS Code extension still ships separately — repackage and republish the .vsix if you want the v2.3.3 a11y improvements in the Marketplace build.

[2.3.2] - 2026-04-14

Major feature release — 15 new capabilities, 6 community PRs merged, 6 new MCP tools, 4 new languages, multi-format export, and graph analysis suite.

Added

  • Hub node detection (get_hub_nodes_tool): find the most-connected nodes in the codebase (architectural hotspots) by in+out degree, excluding File nodes.
  • Bridge node detection (get_bridge_nodes_tool): find architectural chokepoints via betweenness centrality with sampling approximation for graphs >5000 nodes.
  • Knowledge gap analysis (get_knowledge_gaps_tool): identify structural weaknesses — isolated nodes, thin communities (<3 members), untested hotspots, and single-file communities.
  • Surprise scoring (get_surprising_connections_tool): composite scoring for unexpected architectural coupling (cross-community, cross-language, peripheral-to-hub, cross-test-boundary).
  • Suggested questions (get_suggested_questions_tool): auto-generate prioritized review questions from graph analysis (bridge nodes, untested hubs, surprising connections, thin communities).
  • BFS/DFS traversal (traverse_graph_tool): free-form graph exploration from any node with configurable depth (1-6) and token budget.
  • Edge confidence scoring: three-tier system (EXTRACTED/INFERRED/AMBIGUOUS) with float confidence scores on all edges. Schema migration v9.
  • Export formats: GraphML (Gephi/yEd/Cytoscape), Neo4j Cypher statements, Obsidian vault (wikilinks + YAML frontmatter + community pages), SVG static graph. CLI: visualize --format graphml|cypher|obsidian|svg.
  • Graph diff: snapshot/compare graph state over time — new/removed nodes, edges, community membership changes.
  • Token reduction benchmark: measure naive full-corpus tokens vs graph query tokens with per-question reduction ratios.
  • Memory/feedback loop: persist Q&A results as markdown for re-ingestion via save_result / list_memories / clear_memories.
  • Oversized community auto-splitting: communities exceeding 25% of graph are recursively split via Leiden algorithm.
  • 4 new languages: Zig, PowerShell, Julia, Svelte SFC (23 total).
  • Visualization enhancements: node size scaled by degree, community legend with toggle visibility, improved interactivity.
  • README translations: Simplified Chinese, Japanese, Korean, Hindi.

Merged community PRs

  • #127 (xtfer): SQLite compound edge indexes for query performance.
  • #184 (realkotob): batch _compute_summaries — fixes build hangs on large repos.
  • #202 (lngyeen): Swift extension detection, inheritance edges, type kind metadata.
  • #249 (gzenz): community detection resolution scaling (21x speedup), expanded framework patterns, framework-aware dead code detection (56 new tests).
  • #253 (cwoolum): automatic graph build for new worktrees in Claude Code.
  • #267 (jindalarpit): Kiro platform support with 9 tests.

Changed

  • MCP tool count: 22 → 28.
  • Schema version: 8 → 9 (edge confidence columns).
  • Community detection uses resolution scaling for large graphs.
  • Risk scoring uses weighted flow criticality and graduated test coverage.
  • Dead code detection is framework-aware (ORM models, Pydantic, CDK constructs filtered).
  • Flow entry points expanded with 30+ framework decorator patterns.

[2.3.1] - 2026-04-11

Hotfix for the Windows long-running-MCP-tool hang that v2.2.4 only partially fixed.

Fixed

  • Windows MCP hang on long-running tools (PR #231, fixes #46, #136): follow-up to v2.2.4. @dev-limucc reported on #136 that the WindowsSelectorEventLoopPolicy fix from v2.2.4 was necessary but not sufficient — read-only tools worked, but build_or_update_graph_tool(full_rebuild=True) and embed_graph_tool still hung indefinitely on Windows 11 / Python 3.14. Root cause: FastMCP 2.x dispatches sync handlers inline on the only event-loop thread, so handlers that run for more than a few seconds (especially those that spawn subprocesses or do CPU-bound inference) stop the loop from pumping stdin/stdout. Fix: converted the five heavy tools (build_or_update_graph_tool, run_postprocess_tool, embed_graph_tool, detect_changes_tool, generate_wiki_tool) to async def and offloaded the blocking work via asyncio.to_thread. The other 19 tools are fast SQLite-read paths and stay sync. Zero config, works on every platform. New regression tests assert the five tools are registered as coroutines AND that each one's source literally contains asyncio.to_thread as a defense-in-depth lock-in.

[2.3.0] - 2026-04-11

Additive feature release — new language parsers, new platform install target, MCP tool UX improvements, and out-of-tree graph storage. No breaking changes from v2.2.4.

Added

  • Elixir parser (PR #228, closes #112): .ex and .exs files now produce modules as Class nodes, def/defp/defmacro/defmacrop as Function/Test nodes attached to their enclosing module, alias/import/require/use as IMPORTS_FROM edges, and everything else as CALLS edges. Internal call resolution walks into do_block bodies so MathHelpers.double correctly resolves its call to Calculator.compute.
  • Objective-C parser (PR #227, closes #88): .m files parse classes (@interface, @implementation, @protocol), instance and class methods, [receiver message:args] message expressions, C-style main(), and #import/#include. Multi-part selectors like add:to: keep add as the canonical method name.
  • Bash/Shell parser (PR #227, closes #197): .sh, .bash, and .zsh files parse functions, command invocations as CALLS, and source path / . path as IMPORTS_FROM edges with path resolution when the target file exists.
  • Qwen Code as a supported MCP install platform (PR #227, closes #83): code-review-graph install --platform qwen writes a merged ~/.qwen/settings.json using the same mcpServers schema as Cursor/Windsurf — it does not clobber existing Qwen config.
  • apply_refactor_tool dry-run mode (PR #228, closes #176): new dry_run: bool = False parameter on the MCP tool and underlying apply_refactor() function. When true, returns a unified diff per file without touching disk and leaves the refactor_id valid for a follow-up real apply. Multi-edit files now apply sequentially against updated content in both modes (fixes a subtle bug where separate edits on the same file could stomp each other).
  • CRG_DATA_DIR environment variable (PR #228, closes #155): when set, replaces the default <repo>/.code-review-graph directory verbatim. Useful for ephemeral workspaces, Docker volumes, shared CI caches, and multi-repo orchestrators. Supported by the CLI, MCP tools, and the registry.
  • CRG_REPO_ROOT environment variable (PR #228, closes #155): find_project_root() now checks CRG_REPO_ROOT before the usual git-root walk — useful for anyone scripting the CLI from a cwd outside the target repo.
  • install --no-instructions and -y/--yes flags (PR #228, closes #173): new flags on code-review-graph install to opt out of the CLAUDE.md/AGENTS.md/.cursorrules/.windsurfrules injection entirely (--no-instructions) or auto-confirm it without an interactive prompt (-y/--yes). The CLI also now prints the list of files it will touch before writing, so even without --dry-run users see what's coming.
  • Cloud embeddings stderr warning (PR #228, closes #174): get_provider() now prints an explicit warning to stderr before returning a Google Gemini or MiniMax provider, explaining that source code will be sent to an external API. CRG_ACCEPT_CLOUD_EMBEDDINGS=1 suppresses the warning for scripted workflows. The warning is on stderr only — it never writes to stdout or reads from stdin, so the MCP stdio transport remains uncorrupted.
  • TROUBLESHOOTING quick-reference (PR #228): new top section in docs/TROUBLESHOOTING.md covering the four most common support questions — hook schema errors, command not found after pip install, project-vs-user scoping, and "built the graph but Claude Code doesn't see it".

Fixed

  • Multi-edit refactor correctness (PR #228): when a single apply_refactor call had multiple edits targeting the same file, the previous implementation re-read the file once per edit and could silently stomp earlier changes. The plan-computation step now groups edits by file and applies them sequentially against the updated content; this fix applies to both the real-write and the new dry-run path.

Changed

  • install and init commands now preview instruction-file targets before writing (no-op if nothing would change). This is always-on and does not require --dry-run.
  • Default embedding path remains fully local (sentence-transformers); no behavior change unless you explicitly opt in to a cloud provider.

Deprecated

Nothing.

Security

  • The cloud-embedding stderr warning (#174) is a privacy improvement; it does not change the behavior of offline local embeddings, which remain the default.

Upgrade notes

  • Nothing to do beyond uvx --reinstall code-review-graph or pip install -U code-review-graph. If you're coming from v2.2.2 or earlier, re-run code-review-graph install once to pick up the v2.2.3 hook schema rewrite.
  • CRG_DATA_DIR is optional — if you don't set it, graphs continue to live at <repo>/.code-review-graph as before.
  • VS Code extension v0.2.2 (from v2.2.4) still needs to be repackaged and republished separately; the PyPI publish.yml workflow does not cover it.

Superseded PRs

  • PR #204 (install preview, @lngyeen) — reimplemented cleanly in #228 with isatty()-guarded confirmation.
  • PR #207 (CRG_DATA_DIR/CRG_REPO_ROOT, @yashmewada9618) — reimplemented cleanly in #228 without input()-on-stdio and mcp._local_only fragility.
  • PR #179 (cloud embeddings warning, @Bakul2006) — reimplemented cleanly in #228 with stderr-only messaging and no stdio reads.

Credit to @lngyeen, @yashmewada9618, and @Bakul2006 for the original designs.

[2.2.4] - 2026-04-11

Ships the 11 bugs from PR #222 plus the v2.2.3.1 smoke-test hotfixes, for users upgrading directly from v2.2.3 or earlier.

Security

  • fastmcp bumped from 1.0 → ≥2.14.0 (PR #222, fixes #139, #195): closes CVE-2025-62800 (XSS), CVE-2025-62801 (command injection via server_name), CVE-2025-66416 (Confused Deputy). Transitively drops the docket → fakeredis chain that was broken by a FakeConnectionFakeRedisConnection rename in recent fakeredis releases (#195). The FastMCP public API (FastMCP(name, instructions=...), @mcp.tool(), @mcp.prompt(), mcp.run(transport="stdio")) is unchanged across the 1 → 2 bump, so no source changes were needed beyond the pin. All 24 tools verified to register on fastmcp 2.14.6 and round-trip real per-repo data via stdio MCP in a 6-repo smoke test.

Fixed

  • Windows build/embed hangs (PR #222, fixes #46, #136): main() now sets WindowsSelectorEventLoopPolicy before mcp.run() on sys.platform == "win32". The default ProactorEventLoop on Windows Python 3.8+ deadlocks with ProcessPoolExecutor (used by full_build) over a stdio MCP transport — producing the silent "Synthesizing…" hangs on build and embed_graph_tool. This is a no-op on macOS/Linux. Note: the fix was applied blind; maintainer could not verify on Windows. Please open a fresh issue if you still see a hang on v2.2.4 Windows with either sentence-transformers or Gemini providers.
  • Go method receivers (PR #222, fixes #190): func (s *T) Foo() now attaches Foo to T as a member (parent_name="T") with the usual CONTAINS edge instead of appearing as a top-level function. New _get_go_receiver_type() helper walks the method_declaration's first parameter_list to extract the receiver type name.
  • Dart parser — three bugs (PR #222, fixes #87):
    • Dart CALLS edges (_extract_dart_calls_from_children()) — tree-sitter-dart doesn't wrap calls in a single call_expression node; the pattern is identifier + selector > argument_part. New walker handles both direct (print('x')) and method-chained (obj.foo()) shapes.
    • Dart package: URI resolution in _do_resolve_module()package:<pkgname>/<sub_path> now walks up to a pubspec.yaml whose name: declaration matches <pkgname> and resolves to <root>/lib/<sub_path>.
    • inheritors_of bare-vs-qualified name mismatch in tools/query.py — falls back to search_edges_by_target_name(node.name, kind=...) for INHERITS/IMPLEMENTS when the qualified-name lookup returns nothing. Affects all languages (INHERITS targets are stored as bare strings for every language), not just Dart.
  • Nested node_modules and framework ignore defaults (PR #222, fixes #91): _should_ignore() now treats single-segment <dir>/** patterns as "this directory at any depth", so node_modules/** also matches packages/app/node_modules/react/index.js inside monorepos. Extended DEFAULT_IGNORE_PATTERNS with Laravel/Composer (vendor/**, bootstrap/cache/**, public/build/**), Ruby (.bundle/**), Gradle (.gradle/**, *.jar), Flutter/Dart (.dart_tool/**, .pub-cache/**), and generic coverage/**, .cache/**. Deliberately did not add packages/** or bin/**/obj/** — those are false positives in yarn/pnpm workspace monorepos and .NET source trees respectively.
  • Bare except Exception cleanup (PR #222, fixes #194): Replaced with specific exception classes + logger.debug(...) in 11 files (cli.py, graph.py, migrations.py, parser.py, registry.py, tools/context.py, tsconfig_resolver.py, visualization.py, wiki.py, eval/benchmarks/search_quality.py). No behavioral change; debuggability improvement.
  • Visualization auto-collapse hiding all edges (PR #222, fixes #132): visualization.py no longer unconditionally auto-collapses every File node on page load. Auto-collapse now only kicks in above 2000 nodes — previously any graph above ~300 nodes would silently hide every CALLS/IMPORTS/INHERITS edge because they connect Functions/Classes nested inside the collapsed Files.
  • eval command crashes on yaml.safe_load (PR #222, fixes #212): eval.runner.load_all_configs() now calls _require_yaml() before reading YAML, so users without code-review-graph[eval] installed get ImportError: pyyaml is required: pip install code-review-graph[eval] instead of AttributeError: 'NoneType' object has no attribute 'safe_load'.

VS Code extension (0.2.2)

  • better-sqlite3 bumped 11.x → 12.x (PR #222, fixes #218): VS Code 1.115 ships Electron 39 / V8 14.2 which removed v8::Context::GetIsolate(), the C++ API used by better-sqlite3@11. The extension couldn't activate at all — every command was undefined. better-sqlite3@12.4.1+ (installs 12.8.0) uses the new V8 API and ships Electron 39 prebuilds. @types/better-sqlite3: ^7.6.8 → ^7.6.13, plus type-import adjustments in src/backend/sqlite.ts for the Node16 module resolution and the new CJS export = types. Extension version bumped to 0.2.2. Remember to repackage and republish the .vsix — the existing publish.yml workflow only covers PyPI.

Carried forward from 2.2.3.1

  • serve --repo <X> is now honored by all 24 MCP tools (was only read by get_docs_section_tool). See #223.
  • Wiki slug collisions no longer silently overwrite pages (~70% data loss on real repos). See #223.

Upgrade notes

  • uvx --reinstall code-review-graph or pip install -U code-review-graph, then re-run code-review-graph install (the 2.2.3 hook-schema rewrite is still a requirement if you're coming from 2.2.2 or earlier).
  • VS Code extension needs to be repackaged + republished separately; the Python release does not include it.

[2.2.3.1] - 2026-04-11

Hotfix on top of 2.2.3 for two bugs surfaced by a full first-time-user smoke test against six real OSS repos (express, fastapi, flask, gin, httpx, next.js).

Fixed

  • serve --repo <X> was ignored by 21 of 24 MCP tools (PR #223): main.py captured the --repo CLI flag into _default_repo_root, but only get_docs_section_tool read it. The other 21 @mcp.tool() wrappers all took repo_root: Optional[str] = None and passed that straight through to the impl, which fell back to find_repo_root() from cwd. The real-world blast radius is small — the install command writes .mcp.json without a --repo flag and Claude Code launches the server with cwd=<repo> — but anyone scripting serve manually or running a multi-repo orchestrator would silently get the wrong graph. Added a single _resolve_repo_root() helper with explicit precedence (client arg > --repo flag > None → cwd) and threaded it through all 24 wrappers. New unit tests cover the precedence rules.
  • Wiki slug collisions silently overwrote pages (PR #223): _slugify() folds non-alphanumerics to dashes and truncates to 80 chars, so similar community names collided ("Data Processing", "data processing", "Data Processing" all → data-processing.md). generate_wiki() wrote each community to <slug>.md regardless, so later iterations overwrote earlier files while the counter reported them as "updated". On the express smoke test this was ~70% silent data loss (32 real files vs 107 claimed pages). Fixed by tracking used slugs per-run and appending -2, -3, … until unique. Every community now gets its own page; the counter matches the physical file count; get_wiki_page() still resolves by name via the existing partial-match fallback. New regression test monkey-patches three colliding names and asserts no content loss.

[2.2.3] - 2026-04-11

Fixed

  • Claude Code hook schema (PR #208, fixes #97, #138, #163, #168, #172, #182, #188, #191, #201): generate_hooks_config() now emits the valid v1.x+ Claude Code schema — every hook entry has matcher + a nested hooks: [{type, command, timeout}] array, and timeouts are in seconds. The invalid PreCommit event has been removed; pre-commit checks are now installed as a real git hook via install_git_hook(). Users upgrading from 2.2.2 must re-run code-review-graph install to rewrite .claude/settings.json.
  • SQLite transaction nesting (PR #205, fixes #110, #135, #181): GraphStore.__init__ now connects with isolation_level=None, disabling Python's implicit transactions that were the root cause of sqlite3.OperationalError: cannot start a transaction within a transaction on update. store_file_nodes_edges adds a defensive in_transaction flush before BEGIN IMMEDIATE.
  • Go method receivers (PR #166): _extract_name_from_node now resolves Go method names from field_identifier inside method_declaration, fixing method names that were previously picked up as the result type (e.g. int64) instead of the method name.
  • UTF-8 decode errors in detect_changes (PR #170, fixes #169): Diff parsing now uses errors="replace" so diffs containing binary files no longer crash the tool.
  • --platform target scope (PR #142, fixes #133): code-review-graph install --platform <target> now correctly filters skills, hooks, and instruction files so you only get configuration for the requested platform.
  • Large-repo community detection hangs (PR #213, PR #183): Removed recursive sub-community splitting, capped Leiden at n_iterations=2, and batched store_communities writes. 100k+ node graphs no longer hang in _compute_summaries.
  • CI: ruff lint + tomllib on Python 3.10 (PR #220) — tests/test_skills.py now uses a conditional tomli backport on 3.10, N806/E501/W291 fixes in skills.py/communities.py/parser.py, and the embedded noqa reference in visualization.py was rephrased so ruff stops parsing it as a directive.
  • Missing dev dependencies (PR #159): pytest-cov added to dev extras, 50 ruff errors swept, one failing test fixed.
  • JSX component CALLS edges (PR #154): JSX component usage now produces CALLS edges so component-to-component relationships appear in the graph.

Added

  • Codex platform install support (PR #177): code-review-graph install --platform codex appends a mcp_servers.code-review-graph section to ~/.codex/config.toml without overwriting existing Codex settings.
  • Luau language support (PR #165, closes #153): Roblox Luau (.luau) parsing — functions, classes, local functions, requires, tests.
  • REFERENCES edge type (PR #217): New edge kind for symbol references that aren't direct calls (map/dispatch lookups, string-keyed handlers), including Python and TypeScript patterns.
  • recurse_submodules build option (PR #215): Build/update can now optionally recurse into git submodules.
  • .gitignore default for .code-review-graph/ (PR #185): Fresh installs automatically add the SQLite DB directory to .gitignore so the database isn't accidentally committed.
  • Clearer gitignore docs (PR #171, closes #157): Documentation now spells out that code-review-graph already respects .gitignore via git ls-files.

Changed

  • Community detection is now bounded — large repos complete in reasonable time instead of hanging indefinitely.

Fixed

  • install_hooks now merges instead of overwriting (PR #203, fixes #114): install_hooks() previously used dict.update() which clobbered any user-defined hooks in .claude/settings.json. Now merges new entries into existing hook arrays, preserving user hooks. Creates a backup (settings.json.bak) before modification.

[2.2.2] - 2026-04-08

Added

  • Kotlin call extraction: simple_identifier + navigation_expression support for Kotlin method calls (PR #107)
  • JUnit/Kotlin test detection: Annotation-based test classification (@Test, @ParameterizedTest, etc.) for Java/Kotlin/C# (PR #107)

Fixed

  • Windows encoding crash: All write_text/read_text calls in skills.py now use encoding='utf-8' explicitly (PR #152, fixes #147, #148)
  • Invalid --quiet flag in hooks: Removed non-existent --quiet and --json flags from generated hook commands (PR #152, fixes #149)

Housekeeping

  • Untracked .claude-plugin/ directory and added to .gitignore
  • GitHub issue triage: responded to 30+ issues, closed 14, reviewed 24 PRs

[2.2.1] - 2026-04-07

Added

  • Parallel parsing: ProcessPoolExecutor for 3-5x faster builds (CRG_PARSE_WORKERS, CRG_SERIAL_PARSE)
  • Lazy post-processing: postprocess="full"|"minimal"|"none" parameter, run_postprocess MCP tool + CLI command
  • SQLite-native BFS: Recursive CTE replaces NetworkX for impact analysis (CRG_BFS_ENGINE)
  • Configurable limits: CRG_MAX_IMPACT_NODES, CRG_MAX_IMPACT_DEPTH, CRG_MAX_BFS_DEPTH, CRG_MAX_SEARCH_RESULTS
  • Multi-hop dependents: N-hop find_dependents() with CRG_DEPENDENT_HOPS (default 2) and 500-file cap
  • Token-efficient output: detail_level="minimal" on 8 tools for 40-60% token reduction
  • get_minimal_context tool: Ultra-compact entry point (~100 tokens) with task-based tool routing
  • Token-efficient prompts: All 5 MCP prompts rewritten with minimal-first workflows
  • Incremental flow/community updates: incremental_trace_flows(), incremental_detect_communities()
  • Visualization aggregation: Community/file/auto modes with drill-down for large graphs (--mode)
  • Token-efficiency benchmarks: 5 workflow benchmarks in eval/token_benchmark.py
  • DB schema v6: Pre-computed community_summaries, flow_snapshots, risk_index tables
  • Token Efficiency Rules in all skill templates and CLAUDE.md

Changed

  • CLI build/update support --skip-flows, --skip-postprocess flags
  • PostToolUse hook uses --skip-flows for faster incremental updates
  • VS Code extension schema version bumped to v6

Fixed

  • mypy type errors in parallel parsing and context tool
  • Bandit false positive on prompt preamble string
  • Import sorting in graph.py, main.py, tools/__init__.py
  • Unused imports cleaned up in cli.py

Housekeeping

  • Gitignore: untrack marketing-diagram.excalidraw, evaluate/results/, evaluate/reports/
  • Updated FEATURES.md, LLM-OPTIMIZED-REFERENCE.md, CHANGELOG.md for v2.2.1

[2.1.0] - 2026-04-03

Added

  • Jupyter notebook parsing: Parse .ipynb files — extract functions, classes, imports across Python, R, and SQL cells
  • Databricks notebook parsing: Parse Databricks .py notebook exports with # COMMAND ---------- cell boundaries
  • Lua language support: Full parsing for .lua files (functions, local functions, method calls, requires) — 20th language
  • Perl XS support: Parse .xs files with improved Perl call detection and test coverage
  • Zero-config onboarding: install now sets up skills, hooks, and CLAUDE.md by default so the graph is used automatically
  • Platform rule injection: Graph instructions injected into all platform rule files (CLAUDE.md, .cursorrules, etc.) on install
  • Smart install detection: Auto-detects whether installed via uvx or pip and generates correct .mcp.json
  • --platform claude-code alias: Accepts both claude and claude-code as platform names

Fixed

  • JS/TS arrow functions indexed: const foo = () => {} and const bar = function() {} now correctly appear as nodes (#66)
  • importers_of path resolution: Normalized with resolve() to match stored edge targets (#65)
  • Custom embedding models: Support for custom model architectures and restored model param wiring in search (#79)

[2.0.0] - 2026-03-27

Added

  • 12 new features: flows, communities, hybrid search, change analysis, refactoring, hints, prompts, skills, wiki, multi-repo registry, migrations, eval framework
  • 14 new modules (~10,000 lines): flows.py, communities.py, search.py, changes.py, refactor.py, hints.py, prompts.py, skills.py, wiki.py, registry.py, migrations.py, eval/
  • 15 new MCP tools: list_flows, get_flow, get_affected_flows, list_communities, get_community, get_architecture_overview, detect_changes, refactor, apply_refactor, generate_wiki, get_wiki_page, list_repos, cross_repo_search, find_large_functions, semantic_search_nodes
  • 5 MCP prompts: review_changes, architecture_map, debug_issue, onboard_developer, pre_merge_check
  • 7 new CLI commands: detect-changes, wiki, eval, register, unregister, repos, install --skills/--hooks/--all
  • Interactive visualization upgrade: Detail panel, community coloring, flow path highlighting, search-to-zoom, kind filters

Security

  • Fix path traversal in wiki page reader
  • Add regex allowlist for git ref validation
  • Add explicit SSL context for MiniMax API

Fixed

  • Fix git diff argument ordering (broke incremental updates)
  • Fix node_qualified_name schema mismatch in wiki flow query
  • Batch N+1 queries in get_impact_radius and risk scoring

Architecture

  • Decompose _extract_from_tree into 6 focused methods
  • Add 17 public query methods to GraphStore
  • Split tools.py into 10 themed sub-modules

[1.8.4] - 2026-03-20

Added

  • Vue SFC parsing: Parse .vue Single File Components by extracting <script> blocks with automatic lang="ts" detection
  • Solidity support: Full parsing for .sol files (functions, events, modifiers, inheritance)
  • find_large_functions_tool: New MCP tool to find functions, classes, or files exceeding a line-count threshold
  • Call target resolution: Bare call targets resolved to qualified names using same-file definitions (_resolve_call_targets)
  • Multi-word AND search: search_nodes now requires all words to match (case-insensitive)
  • Impact radius pagination: get_impact_radius returns truncated flag, total_impacted count, and accepts max_results parameter

Changed

  • Language count updated from 12 to 14 across all documentation
  • MCP tool count updated from 8 to 9 across all documentation
  • VS Code extension updated to v0.2.0 with 5 new commands documented

Fixed

  • Test assertions updated to handle qualified call targets from _resolve_call_targets

[1.8.3] - 2026-03-20

Fixed

  • Parser recursion guard: Added _MAX_AST_DEPTH = 180 limit to _extract_from_tree() preventing stack overflow on deeply nested ASTs
  • Module cache bound: Added _MODULE_CACHE_MAX = 15_000 with automatic eviction to prevent unbounded memory growth in _module_file_cache
  • Embeddings thread safety: Added check_same_thread=False to EmbeddingStore SQLite connection
  • Embeddings retry logic: Added _call_with_retry() with exponential backoff for Google Gemini API calls
  • Visualization XSS hardening: Added </ to <\/ replacement in JSON serialization to prevent script injection
  • CLI error handling: Split broad except into specific json.JSONDecodeError and (KeyError, TypeError) handlers
  • Git timeout: Made configurable via CRG_GIT_TIMEOUT environment variable (default 30s)

Added

  • Governance files: Added CONTRIBUTING.md, SECURITY.md, CODE_OF_CONDUCT.md
  • Project URLs: Added Homepage, Repository, Issues, Changelog URLs to pyproject.toml metadata

[1.8.2] - 2026-03-17

Fixed

  • C# parsing broken: Renamed language identifier from c_sharp to csharp to match tree-sitter-language-pack's actual identifier. Previously, all C# files were silently skipped because _get_parser() swallowed the LookupError.

[1.8.1] - 2026-03-17

Fixed

  • Add missing max_nodes parameter to get_impact_radius method signature (caused NameError at runtime)
  • Fix .gitignore test assertion to match expanded comment format

[1.8.0] - 2026-03-17

Security

  • Prompt injection mitigation: Node names are now sanitized (control characters stripped, length capped at 256) before appearing in MCP tool responses, preventing graph-laundered prompt injection attacks
  • Path traversal protection: repo_root parameter now validates that the target directory contains a .git or .code-review-graph directory, preventing arbitrary file exfiltration via MCP tools
  • VSCode RCE fix: cliPath setting is now scoped to machine level only, preventing malicious workspace settings from pointing to attacker-controlled binaries
  • XSS fix in visualization: escH() now escapes quotes and backticks in addition to angle brackets, closing stored XSS via crafted node names in generated HTML
  • SRI for CDN assets: D3.js script tag now includes integrity and crossorigin attributes to prevent CDN compromise
  • Secure nonce generation: VSCode webview CSP nonces now use crypto.randomBytes() instead of Math.random()
  • Symlink protection: Build, watch mode, and file collection now skip symbolic links to prevent parsing files outside the repository
  • TOCTOU elimination: File bytes are now read once, then hashed and parsed from the same buffer, closing the time-of-check-to-time-of-use gap

Fixed

  • Thread-safe NetworkX cache: Added threading.Lock around graph cache reads/writes to prevent race conditions between watch mode and MCP request handling
  • BFS resource limits: Impact radius traversal now caps at 500 nodes to prevent memory exhaustion on dense graphs
  • SQL parameter batching: get_edges_among now batches queries to stay under SQLite's variable limit on large node sets
  • Database path leakage: Improved .gitignore inside .code-review-graph/ with explicit warnings about absolute paths in the database

Changed

  • Pinned dependency bounds: All dependencies now have upper-bound version constraints to mitigate supply-chain risks

[1.7.2] - 2026-03-09

Fixed

  • Watch mode thread safety: SQLite connections now use check_same_thread=False for Python 3.10/3.11 compatibility with watchdog's background threads
  • Full rebuild stale data: full_build now purges nodes/edges from files deleted since last build
  • Removed unused dependency: gitpython was listed in dependencies but never imported — removed to shrink install footprint
  • Stale Docker reference: Removed non-existent Docker image suggestion from Python version check

[1.7.0] - 2026-03-09

Added

  • install command — primary entry point for new users (code-review-graph install). init remains as an alias for backwards compatibility.
  • --dry-run flag on install/init — shows what would be written without modifying files
  • PyPI publish workflow — GitHub releases now automatically publish to PyPI via API token
  • Professional README — complete rewrite with real benchmark data:
    • Code reviews: 6.8x average token reduction (tested on httpx, FastAPI, Next.js)
    • Live coding tasks: 14.1x average, up to 49.1x on large repos

Changed

  • README restructured around the install-and-forget user experience
  • CLI banner now shows install as the primary command

[1.6.4] - 2026-03-06

Changed

  • Portable MCP config: init now generates uvx-based .mcp.json instead of absolute Python paths — works on any machine with uv installed
  • Removed _safe_path symlink workaround (no longer needed with uvx)

[1.6.3] - 2026-03-06

Added

  • SessionStart hook — Claude Code now automatically prefers graph MCP tools over full codebase scans at the start of every session, saving tokens on general queries
  • homepage and author.url fields in plugin.json for marketplace discoverability

Fixed

  • plugin.json schema: renamed tags to keywords, removed invalid skills path (auto-discovered from default location)
  • Removed screenshot placeholder section from README

[1.6.2] - 2026-02-27

Fixed

  • Critical: Incremental hash comparison bug — file_hash read from wrong field, causing every file to re-parse
  • Watch mode on_deleted handler now filters by ignore patterns
  • Removed dead code in full_build and duplicate main() in incremental.py
  • get_staged_and_unstaged handles git renamed files (R old -> new)
  • TROUBLESHOOTING.md hook config path corrected

Added

  • Parser: C/C++ support — full node extraction (structs, classes, functions, includes, calls, inheritance)
  • Parser: name extraction fixes for Kotlin/Swift (simple_identifier), Ruby (constant), C/C++ nested function_declarator
  • GraphStore context manager (__enter__/__exit__)
  • get_all_edges() and get_edges_among() public methods on GraphStore
  • NetworkX graph caching with automatic invalidation on writes
  • Subprocess timeout (30s) on all git calls
  • Progress logging every 50 files in full build
  • SHA-256 hashing in embeddings (replaced MD5)
  • Chunked embedding search (fetchmany(500))
  • Batch edge collection in get_impact_radius (single SQL query)
  • ARIA labels throughout D3.js visualization
  • CI: Coverage enforcement (--cov-fail-under=50), bandit security scanning, mypy type checking
  • Tests: test_incremental.py (24 tests), test_embeddings.py (16 tests)
  • Test fixtures: C, C++, C#, Ruby, PHP, Kotlin, Swift with multilang test classes
  • Docs: API response schemas in COMMANDS.md, ignore patterns in USAGE.md

[1.5.3] - 2026-02-27

Fixed

  • init now auto-creates symlinks when paths contain spaces (macOS iCloud, OneDrive, etc.)
  • build, status, visualize, watch work without a git repository (falls back to cwd)
  • Skills discoverable via plugin.json (name field added to SKILL.md frontmatter)

[1.5.0] - 2026-02-26

Added

  • File organization: All generated files now live in .code-review-graph/ directory instead of repo root
    • Auto-created .gitignore inside the directory prevents accidental commits
    • Automatic migration from legacy .code-review-graph.db at repo root
  • Visualization: start collapsed: Only File nodes visible on load; click to expand children
  • Visualization: search bar: Filter nodes by name or qualified name in real-time
  • Visualization: edge type toggles: Click legend items to show/hide edge types (Calls, Imports, Inherits, Contains)
  • Visualization: scale-aware layout: Force simulation adapts charge, distance, and decay for large graphs (300+ nodes)

Changed

  • Database path: .code-review-graph.db.code-review-graph/graph.db
  • HTML visualization path: .code-review-graph.html.code-review-graph/graph.html
  • .code-review-graph/** added to default ignore patterns (prevents self-indexing)

Removed

  • references/ directory (duplicate of docs/, caused stale path references)
  • agents/ directory (unused, not wired into any code)
  • settings.json at repo root (decorative, not loaded by code)

[1.4.0] - 2026-02-26

Added

  • init command: automatic .mcp.json setup for Claude Code integration
  • visualize command: interactive D3.js force-directed graph visualization
  • serve command: start MCP server directly from CLI

Changed

  • Comprehensive documentation overhaul across all reference files

[1.3.0] - 2026-02-26

Added

  • Universal installation: now works with pip install code-review-graph[embeddings] on Python 3.10+
  • CLI entry point (code-review-graph command works after normal pip install)
  • Clear Python version check with helpful Docker fallback for older Python users
  • Improved README installation section with one-command + Docker option

Changed

  • Minimum Python requirement lowered from 3.11 → 3.10 (covers ~90% of users)

Fixed

  • Installation friction for most developers