64 KiB
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.tomlinto 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.ymlbuilds/restores the graph from CI cache, runsdetect-changesagainst 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_baselineeval 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_batchis now guarded against open transactions like its sibling (#489, merged from community PR #529 by @Devilthelegend — thank you).- Windows:
daemon statusno longer crashes with WinError 87 (#511): PID liveness now usesOpenProcess/WaitForSingleObjecton win32 instead ofos.kill(pid, 0). - Windows: CLI
detect-changesmapped 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_changescalls are markedstatus=errorand 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()). installgit hooks now resolve the real hooks directory viagit rev-parse --git-path hooks, so linked worktrees andcore.hooksPath(husky) setups get a working pre-commit hook (#313 residue).- Shipped
hooks/hooks.jsonandhooks/session-start.shnow drain stdin, matching the generated configs (#493 class). fastmcpis now capped<4so 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 Savingspanel on every--briefCLI call. Bothcode-review-graph detect-changes --briefand the newcode-review-graph update --briefprint 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 │ └──────────────────────────────────────────────────────────────┘ -
--verifyflag cross-checks the displayed numbers against OpenAI'scl100k_basetokenizer (the GPT-4 family). Adds a secondVerified (tiktoken)row to the panel showing the real token counts. Requirespip install tiktoken. A one-time calibration across 222 mixed source files (Python/JS/TS/Go/Rust/RST/MD) committed indocs/REPRODUCING.mdshows thechars/4approximation 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 fromdetect-changes --brief(which is read-only against the existing graph). Useupdate --briefwhen the graph might be stale (post-rebase, large change set); usedetect-changes --briefwhen hooks/crg-daemonhave 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_retrievalbenchmark — 11 hand-curated 2-step tool-chain tasks (semantic_search → query_graph) across the 6 test repos. Average score 0.909. Per-task CSV inevaluate/results/.code-review-graph embedCLI 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/*.yamlnow pins an upstream SHA. Previously every config usedcommit: HEAD, which made benchmarks drift whenever upstream pushed. Pinned SHAs: expressb4ab7d65, fastapi0227991a, flaska29f88ce, gin5c00df8a, httpxb55d4635, code-review-graph84bde354. nextjs.yamlrenamed tocode-review-graph.yaml. The historical "nextjs" entry pointed at this repo, not a Next.js codebase. Renamed to match reality.eval/runner.pyuses full clones with explicitreturncodechecks. Previously--depth 50silently fell back toHEAD~1..HEADwhenever 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, default42). Previously unseeded — community IDs and sizes drifted run-to-run on the same graph, breaking benchmark comparability. eval/runner.pyresolves 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.pycallsrun_post_processingafterfull_build. Previously the eval framework left FTS5 unpopulated (shadow tablesnodes_fts_idxandnodes_fts_docsizeempty), so downstream search and multi-hop benchmarks silently returned no results.
Changed — Search and embeddings
embeddings._node_to_textis 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_namesever slip into the graph (e.g. after a path-normalization mismatch), theUntested:line in the human summary now collapses to unique names. The underlyingtest_gapslist still carries every entry. token_benchmark.pywarns 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 toembed.
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.mdToken Savings section (new collapsible block under Usage). Plain-English explanation ofdetect-changes --briefvsupdate --brief— read-only vs re-parses-first — with a side-by-side decision table.docs/COMMANDS.mdlists the new--brief,--verify, andembedforms 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--verifycross-check. Rendered fromdiagrams/context-savings-demo.tape(regenerable withvhs).
[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_savingsfield 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 compactcontext_savingsmetadata.
Changed
- Architecture overview is compact by default:
get_architecture_overview_toolnow defaults todetail_level="minimal", dropping per-community member lists and aggregating cross-community edges by community pair. Full per-edge output remains available withdetail_level="standard". - Bounded change analysis:
detect_changes_toolcan now cap very large changed-function and transitive-test frontiers withCRG_MAX_CHANGED_FUNCSandCRG_MAX_TRANSITIVE_FRONTIER, and can return a structured timeout error viaCRG_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 produceTestnodes. - 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_ofnow 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_sectioncan load the packagedLLM-OPTIMIZED-REFERENCE.mdfrom installed wheels. - Local embedding provider availability (#484/#448): missing
sentence-transformersnow 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, andlanguagewhile preserving the legacyfilekey. - SVN root validation (#456): MCP/daemon/registry root validation now accepts
.svnworking copies consistently. - CLI postprocess flags (#487):
build --skip-postprocessandupdate --skip-flowsno 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.2changelog 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):
.nixfiles are parsed via thenixtree-sitter grammar shipped withtree-sitter-language-pack. Top-level and nested attrset bindings becomeFunctionnodes with flattened dotted names (e.g.packages.default,devShells.default). Inflake.nix,inputs.<name>.url = "..."strings emitIMPORTS_FROMedges to the URL;import <path>andcallPackage <path> <args>applications in any.nixfile emitIMPORTS_FROMedges (relative paths are resolved against the caller's directory). Adds 7 tests (TestNixParsing) and fixturestests/fixtures/sample.nix,tests/fixtures/sample_module.nix. - GDScript support (Godot, PR #316):
.gdfiles are parsed via thegdscripttree-sitter grammar. Extracts inner classes (class Name:), the file-levelclass_nameidentity, functions (includingstatic func),extendsparent class as an IMPORTS_FROM edge, direct calls and method calls. Adds 10 tests andtests/fixtures/sample.gd. - Verilog / SystemVerilog support (PR #428):
.v,.sv,.svhfiles parse modules, classes, packages, interfaces, programs, functions, and tasks via theverilogtree-sitter grammar. Per-construct extractors with dedicated unit tests. - SQL support (PR #398):
.sqlfiles parseCREATE FUNCTION,CREATE PROCEDURE,CREATE TABLE, andCREATE VIEWstatements; emits CALLS edges for function invocations. - ReScript support (PR #309/323):
.res/.resiparsing for modules, let-bindings, and external declarations. .hhextension support: C++ header variants now resolve into the C++ parser path..kshextension and shebang-based detection (PR #276):.kshfiles parsed as shell; extension-less scripts detected via#!/usr/bin/env <lang>shebang lines.- Julia improvements: parametric constructors,
@enumdeclarations, andpublicmodule exports now produce graph nodes.
Platforms and install targets
- GitHub Copilot platform support (PR #445):
code-review-graph install --platform copilotwrites Copilot-CLI-compatible MCP config without generating Claude-specific skill artifacts. - Gemini CLI platform support (PR #391):
--platform gemini-cliskips Claude skills and writes Gemini-native MCP config. - Qoder platform support (PR #245):
--platform qoderadds MCP server registration for Qoder. - OpenCode plugin support (PR #198 via #366):
--platform opencoderegisters the MCP server with the OpenCode plugin manifest. - Cursor hooks support (PR #196):
installnow writes Cursor hook entries (gated behind~/.cursordetection 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 viasubprocess.Popenchild 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 --toolsflag andCRG_TOOLSenv var: MCP tool filtering at startup so callers can expose only the subset they need.--repoprecedence and validation inget_docs_section(PR #378): honorsserve --repoand 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_DIRmechanism, 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 concreteInjectedType.method. EmitsINJECTSedges and stereotype metadata (@Service,@Component,@Repository,@Controller); writes fully-qualifiedtarget_qualifiedsocallers_ofqueries work. - Temporal workflow/activity call resolution:
WorkflowStub.start(...)andActivityStub.execute(...)resolve to their concrete workflow/activity implementations. - Kafka consumer/producer detection:
@KafkaListener-annotated methods andKafkaTemplate.send(...)calls emitCONSUMESandPRODUCESedges 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 emitREFERENCESedges 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:testare 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.symbolshapes 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_ONedge types rendered in the standalone HTML visualization.
Fixed
__version__ reporting
code_review_graph.__version__now matchespyproject.toml(was2.1.0since the v2.1.0 release). The User-Agent header thatembeddings.pysends 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
identifierchild ofmethod_declarationrather than the return-type child (which was producing names likeint64). - Java superclass / super-interfaces (PR #278):
extends Fooandimplements Bar, Baznow extract bare type names from thesuperclass/super_interfacesAST nodes. - Java import resolution to file paths (PR #280):
import com.example.foo.Barresolves throughsrc/main/java/...and configured source roots to the actual file. - PHP
CALLextraction (PR #298): method calls ($obj->foo()), static calls (Foo::bar()), and unqualified function calls now produce CALLS edges. - Module-scope
CALLSedges (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/svnsubprocesses now run withstdin=DEVNULL, preventing the FastMCP-stdio buffer from filling on Windows. - Windows non-UTF-8 locale:
subprocess.runcalls now passencoding="utf-8"so cp1252 hosts no longer mis-decode git output. - Windows test failures (PR #274): UTF-8 encoding, CRLF normalization, and
stop_atboundary handling fixes for Windows CI.
Hooks and install
- Hooks JSON schema (PR #288):
hooks.jsonvalidation no longer fails on the wrapper layout —matcheris required and the wrapper is removed. - Hooks merge instead of overwrite (PR #114, PR #145, PR #203):
install_hooksnow merges into existing hook arrays and creates asettings.json.bakbackup before modifying user config. - Pre-commit hook adds
updatecommand (PR #315): generated pre-commit hook runscode-review-graph updaterather than the obsolete subcommand. - Skip hooks gracefully outside git (PR #293):
installno longer fails when invoked from a non-git directory. - Poetry / uv environment detection (PR #287):
installnow generates the correct MCP serve command for projects using Poetry or uv. - Hook quoting and
docsrepo_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_filterrestored on fastmcp ≥3, dependency floor bumped tofastmcp>=3.2.4to 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 writescwdinto 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 manualbuildbeforereconcile.- Flow trace adjacency in-memory (PR #296):
trace_flowsloads adjacency once instead of querying SQLite per hop.
Other
UnicodeDecodeErrorinread_text(PR #303): all text reads now useerrors="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.
statuscommand 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.pydiagnostic script. - MseeP.ai badge added to README (PR #399).
Maintenance
- Beads (
bd) issue tracking initialized for the project (bd primefor 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-graphorpip install -U code-review-graph.- Re-run
code-review-graph installonce after upgrading to pick up the JSONC-tolerant config writer and the correctedcwd/ skills path in.mcp.json. - The
__version__fix changes the User-Agent string emitted by cloud embedding providers fromcode-review-graph/2.1.0tocode-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
.vsixif 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
WindowsSelectorEventLoopPolicyfix from v2.2.4 was necessary but not sufficient — read-only tools worked, butbuild_or_update_graph_tool(full_rebuild=True)andembed_graph_toolstill 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) toasync defand offloaded the blocking work viaasyncio.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 containsasyncio.to_threadas 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):
.exand.exsfiles now produce modules as Class nodes,def/defp/defmacro/defmacropas Function/Test nodes attached to their enclosing module,alias/import/require/useasIMPORTS_FROMedges, and everything else asCALLSedges. Internal call resolution walks intodo_blockbodies soMathHelpers.doublecorrectly resolves its call toCalculator.compute. - Objective-C parser (PR #227, closes #88):
.mfiles parse classes (@interface,@implementation,@protocol), instance and class methods,[receiver message:args]message expressions, C-stylemain(), and#import/#include. Multi-part selectors likeadd:to:keepaddas the canonical method name. - Bash/Shell parser (PR #227, closes #197):
.sh,.bash, and.zshfiles parse functions,commandinvocations asCALLS, andsource path/. pathasIMPORTS_FROMedges 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 qwenwrites a merged~/.qwen/settings.jsonusing the samemcpServersschema as Cursor/Windsurf — it does not clobber existing Qwen config. apply_refactor_tooldry-run mode (PR #228, closes #176): newdry_run: bool = Falseparameter on the MCP tool and underlyingapply_refactor()function. When true, returns a unified diff per file without touching disk and leaves therefactor_idvalid 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_DIRenvironment variable (PR #228, closes #155): when set, replaces the default<repo>/.code-review-graphdirectory 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_ROOTenvironment variable (PR #228, closes #155):find_project_root()now checksCRG_REPO_ROOTbefore the usual git-root walk — useful for anyone scripting the CLI from a cwd outside the target repo.install --no-instructionsand-y/--yesflags (PR #228, closes #173): new flags oncode-review-graph installto opt out of theCLAUDE.md/AGENTS.md/.cursorrules/.windsurfrulesinjection 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-runusers 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=1suppresses 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.mdcovering the four most common support questions — hook schema errors,command not foundafter 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_refactorcall 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
installandinitcommands 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-graphorpip install -U code-review-graph. If you're coming from v2.2.2 or earlier, re-runcode-review-graph installonce to pick up the v2.2.3 hook schema rewrite. CRG_DATA_DIRis optional — if you don't set it, graphs continue to live at<repo>/.code-review-graphas before.- VS Code extension v0.2.2 (from v2.2.4) still needs to be repackaged and republished separately; the PyPI
publish.ymlworkflow 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 withoutinput()-on-stdio andmcp._local_onlyfragility. - 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 → fakeredischain that was broken by aFakeConnection→FakeRedisConnectionrename 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 setsWindowsSelectorEventLoopPolicybeforemcp.run()onsys.platform == "win32". The defaultProactorEventLoopon Windows Python 3.8+ deadlocks withProcessPoolExecutor(used byfull_build) over a stdio MCP transport — producing the silent "Synthesizing…" hangs onbuildandembed_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 eithersentence-transformersor Gemini providers. - Go method receivers (PR #222, fixes #190):
func (s *T) Foo()now attachesFootoTas a member (parent_name="T") with the usualCONTAINSedge 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
CALLSedges (_extract_dart_calls_from_children()) — tree-sitter-dart doesn't wrap calls in a singlecall_expressionnode; the pattern isidentifier + 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 apubspec.yamlwhosename:declaration matches<pkgname>and resolves to<root>/lib/<sub_path>. inheritors_ofbare-vs-qualified name mismatch intools/query.py— falls back tosearch_edges_by_target_name(node.name, kind=...)forINHERITS/IMPLEMENTSwhen the qualified-name lookup returns nothing. Affects all languages (INHERITS targets are stored as bare strings for every language), not just Dart.
- Dart
- Nested
node_modulesand framework ignore defaults (PR #222, fixes #91):_should_ignore()now treats single-segment<dir>/**patterns as "this directory at any depth", sonode_modules/**also matchespackages/app/node_modules/react/index.jsinside monorepos. ExtendedDEFAULT_IGNORE_PATTERNSwith Laravel/Composer (vendor/**,bootstrap/cache/**,public/build/**), Ruby (.bundle/**), Gradle (.gradle/**,*.jar), Flutter/Dart (.dart_tool/**,.pub-cache/**), and genericcoverage/**,.cache/**. Deliberately did not addpackages/**orbin/**/obj/**— those are false positives in yarn/pnpm workspace monorepos and .NET source trees respectively. - Bare
except Exceptioncleanup (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.pyno 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. evalcommand crashes onyaml.safe_load(PR #222, fixes #212):eval.runner.load_all_configs()now calls_require_yaml()before reading YAML, so users withoutcode-review-graph[eval]installed getImportError: pyyaml is required: pip install code-review-graph[eval]instead ofAttributeError: 'NoneType' object has no attribute 'safe_load'.
VS Code extension (0.2.2)
better-sqlite3bumped 11.x → 12.x (PR #222, fixes #218): VS Code 1.115 ships Electron 39 / V8 14.2 which removedv8::Context::GetIsolate(), the C++ API used bybetter-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 insrc/backend/sqlite.tsfor theNode16module resolution and the new CJSexport =types. Extension version bumped to 0.2.2. Remember to repackage and republish the.vsix— the existingpublish.ymlworkflow only covers PyPI.
Carried forward from 2.2.3.1
serve --repo <X>is now honored by all 24 MCP tools (was only read byget_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-graphorpip install -U code-review-graph, then re-runcode-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.pycaptured the--repoCLI flag into_default_repo_root, but onlyget_docs_section_toolread it. The other 21@mcp.tool()wrappers all tookrepo_root: Optional[str] = Noneand passed that straight through to the impl, which fell back tofind_repo_root()from cwd. The real-world blast radius is small — theinstallcommand writes.mcp.jsonwithout a--repoflag and Claude Code launches the server withcwd=<repo>— but anyone scriptingservemanually or running a multi-repo orchestrator would silently get the wrong graph. Added a single_resolve_repo_root()helper with explicit precedence (client arg >--repoflag >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>.mdregardless, 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 hasmatcher+ a nestedhooks: [{type, command, timeout}]array, and timeouts are in seconds. The invalidPreCommitevent has been removed; pre-commit checks are now installed as a real git hook viainstall_git_hook(). Users upgrading from 2.2.2 must re-runcode-review-graph installto rewrite.claude/settings.json. - SQLite transaction nesting (PR #205, fixes #110, #135, #181):
GraphStore.__init__now connects withisolation_level=None, disabling Python's implicit transactions that were the root cause ofsqlite3.OperationalError: cannot start a transaction within a transactiononupdate.store_file_nodes_edgesadds a defensivein_transactionflush beforeBEGIN IMMEDIATE. - Go method receivers (PR #166):
_extract_name_from_nodenow resolves Go method names fromfield_identifierinsidemethod_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 useserrors="replace"so diffs containing binary files no longer crash the tool. --platformtarget 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 batchedstore_communitieswrites. 100k+ node graphs no longer hang in_compute_summaries. - CI: ruff lint +
tomllibon Python 3.10 (PR #220) —tests/test_skills.pynow uses a conditionaltomlibackport on 3.10,N806/E501/W291fixes inskills.py/communities.py/parser.py, and the embeddednoqareference invisualization.pywas rephrased so ruff stops parsing it as a directive. - Missing dev dependencies (PR #159):
pytest-covadded 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 codexappends amcp_servers.code-review-graphsection to~/.codex/config.tomlwithout 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_submodulesbuild option (PR #215): Build/update can now optionally recurse into git submodules..gitignoredefault for.code-review-graph/(PR #185): Fresh installs automatically add the SQLite DB directory to.gitignoreso the database isn't accidentally committed.- Clearer gitignore docs (PR #171, closes #157): Documentation now spells out that
code-review-graphalready respects.gitignoreviagit ls-files.
Changed
- Community detection is now bounded — large repos complete in reasonable time instead of hanging indefinitely.
Fixed
install_hooksnow merges instead of overwriting (PR #203, fixes #114):install_hooks()previously useddict.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_expressionsupport 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_textcalls inskills.pynow useencoding='utf-8'explicitly (PR #152, fixes #147, #148) - Invalid
--quietflag in hooks: Removed non-existent--quietand--jsonflags 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:
ProcessPoolExecutorfor 3-5x faster builds (CRG_PARSE_WORKERS,CRG_SERIAL_PARSE) - Lazy post-processing:
postprocess="full"|"minimal"|"none"parameter,run_postprocessMCP 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()withCRG_DEPENDENT_HOPS(default 2) and 500-file cap - Token-efficient output:
detail_level="minimal"on 8 tools for 40-60% token reduction get_minimal_contexttool: 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_indextables - Token Efficiency Rules in all skill templates and CLAUDE.md
Changed
- CLI
build/updatesupport--skip-flows,--skip-postprocessflags - PostToolUse hook uses
--skip-flowsfor 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
.ipynbfiles — extract functions, classes, imports across Python, R, and SQL cells - Databricks notebook parsing: Parse Databricks
.pynotebook exports with# COMMAND ----------cell boundaries - Lua language support: Full parsing for
.luafiles (functions, local functions, method calls, requires) — 20th language - Perl XS support: Parse
.xsfiles with improved Perl call detection and test coverage - Zero-config onboarding:
installnow 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-codealias: Accepts bothclaudeandclaude-codeas platform names
Fixed
- JS/TS arrow functions indexed:
const foo = () => {}andconst bar = function() {}now correctly appear as nodes (#66) importers_ofpath resolution: Normalized withresolve()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_nameschema mismatch in wiki flow query - Batch N+1 queries in
get_impact_radiusand risk scoring
Architecture
- Decompose
_extract_from_treeinto 6 focused methods - Add 17 public query methods to
GraphStore - Split
tools.pyinto 10 themed sub-modules
[1.8.4] - 2026-03-20
Added
- Vue SFC parsing: Parse
.vueSingle File Components by extracting<script>blocks with automaticlang="ts"detection - Solidity support: Full parsing for
.solfiles (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_nodesnow requires all words to match (case-insensitive) - Impact radius pagination:
get_impact_radiusreturnstruncatedflag,total_impactedcount, and acceptsmax_resultsparameter
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 = 180limit to_extract_from_tree()preventing stack overflow on deeply nested ASTs - Module cache bound: Added
_MODULE_CACHE_MAX = 15_000with automatic eviction to prevent unbounded memory growth in_module_file_cache - Embeddings thread safety: Added
check_same_thread=FalsetoEmbeddingStoreSQLite 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
exceptinto specificjson.JSONDecodeErrorand(KeyError, TypeError)handlers - Git timeout: Made configurable via
CRG_GIT_TIMEOUTenvironment 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_sharptocsharpto matchtree-sitter-language-pack's actual identifier. Previously, all C# files were silently skipped because_get_parser()swallowed theLookupError.
[1.8.1] - 2026-03-17
Fixed
- Add missing
max_nodesparameter toget_impact_radiusmethod signature (causedNameErrorat runtime) - Fix
.gitignoretest 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_rootparameter now validates that the target directory contains a.gitor.code-review-graphdirectory, preventing arbitrary file exfiltration via MCP tools - VSCode RCE fix:
cliPathsetting is now scoped tomachinelevel 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
integrityandcrossoriginattributes to prevent CDN compromise - Secure nonce generation: VSCode webview CSP nonces now use
crypto.randomBytes()instead ofMath.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.Lockaround 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_amongnow batches queries to stay under SQLite's variable limit on large node sets - Database path leakage: Improved
.gitignoreinside.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=Falsefor Python 3.10/3.11 compatibility with watchdog's background threads - Full rebuild stale data:
full_buildnow purges nodes/edges from files deleted since last build - Removed unused dependency:
gitpythonwas 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
installcommand — primary entry point for new users (code-review-graph install).initremains as an alias for backwards compatibility.--dry-runflag oninstall/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
installas the primary command
[1.6.4] - 2026-03-06
Changed
- Portable MCP config:
initnow generatesuvx-based.mcp.jsoninstead of absolute Python paths — works on any machine withuvinstalled - Removed
_safe_pathsymlink workaround (no longer needed withuvx)
[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
homepageandauthor.urlfields in plugin.json for marketplace discoverability
Fixed
- plugin.json schema: renamed
tagstokeywords, removed invalidskillspath (auto-discovered from default location) - Removed screenshot placeholder section from README
[1.6.2] - 2026-02-27
Fixed
- Critical: Incremental hash comparison bug —
file_hashread from wrong field, causing every file to re-parse - Watch mode
on_deletedhandler now filters by ignore patterns - Removed dead code in
full_buildand duplicatemain()inincremental.py get_staged_and_unstagedhandles 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++ nestedfunction_declarator GraphStorecontext manager (__enter__/__exit__)get_all_edges()andget_edges_among()public methods onGraphStore- 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
initnow auto-creates symlinks when paths contain spaces (macOS iCloud, OneDrive, etc.)build,status,visualize,watchwork without a git repository (falls back to cwd)- Skills discoverable via plugin.json (
namefield 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
.gitignoreinside the directory prevents accidental commits - Automatic migration from legacy
.code-review-graph.dbat repo root
- Auto-created
- 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 ofdocs/, caused stale path references)agents/directory (unused, not wired into any code)settings.jsonat repo root (decorative, not loaded by code)
[1.4.0] - 2026-02-26
Added
initcommand: automatic.mcp.jsonsetup for Claude Code integrationvisualizecommand: interactive D3.js force-directed graph visualizationservecommand: 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-graphcommand 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