33 Commits

Author SHA1 Message Date
Tirth Kanani 9faeb54955 Merge remote-tracking branch 'origin/main' into fix/issue-475-visualize-serve-cors
# Conflicts:
#	code_review_graph/visualization.py
2026-07-30 21:53:53 +01:00
Tirth Kanani c5e3b1ce3a fix(visualization): substitute D3 script tags before graph data
The D3 placeholder replacement ran over the already-interpolated graph
JSON, so repo-derived content literally named __D3_SCRIPTS__ was expanded
into script markup inside the graphData script, truncating it and
promoting the remaining JSON to live HTML. Substitute the trusted
template placeholders scripts-first, data-last, and add a regression
test with a node named __D3_SCRIPTS__ and an HTML-shaped symbol name.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FmPUotoqsNWWt3b41FMjwv
2026-07-30 21:36:08 +01:00
Tirth Kanani ee4eac1b5b fix(visualization): load D3 from a vendored same-origin asset so visualize --serve works offline (#475)
The generated graph HTML loaded D3 only from the d3js.org CDN, so on
offline or filtered networks (the reporter's case) the script was blocked
and the page failed with 'd3 is not defined'. The CDN tag already carried
integrity + crossorigin, so the failure was the external fetch itself.

- Vendor the pinned d3 v7.9.0 build (byte-identical to the existing SRI
  hash) as code_review_graph/assets/d3.v7.min.js; hatchling packages it
  in both wheel and sdist.
- generate_html now writes the asset next to graph.html (verified against
  the pinned sha384 before writing) and both templates reference the
  same-origin file first, keeping the integrity attribute.
- A synchronous document.write fallback keeps the SRI + crossorigin CDN
  tag for pages copied away from their d3 sidecar file.
- Regression tests: same-origin script tag with pinned SRI, SRI-pinned
  CDN fallback, sidecar asset written into the served directory, and
  packaged asset hash check.

Fixes #475

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FmPUotoqsNWWt3b41FMjwv
2026-07-30 21:08:02 +01:00
Tirth Kanani 75dbc4c359 fix(visualization): make auto mode consider edge count, fall back to file aggregation (#609)
Auto mode switched away from the full D3 force layout only when node
count exceeded 3000; edge count was ignored, so a 2792-node/17488-edge
graph stayed in full mode and the force layout stalled the browser
(O(E) link force per tick plus one SVG element per edge).

- Add DEFAULT_MAX_FULL_EDGES = 3 * DEFAULT_MAX_FULL_NODES (9000),
  derived from the ~3 edges/node budget the node cap already tolerated
- Auto mode now switches when rendered nodes > max_full_nodes OR
  rendered edges > max_full_edges
- When switching without community data, fall back to file aggregation
  instead of collapsing everything into one Uncategorized super-node
- Regression tests cover the exact reported 2792/17488 boundary

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FmPUotoqsNWWt3b41FMjwv
2026-07-30 21:05:16 +01:00
Tirth Kanani a7954cb9ab fix(visualization): recover responsive graph layout
Keep both generated graph modes centered across delayed paint and viewport resize, with bounded requestAnimationFrame retries when SVG bounds are temporarily zero.

Co-authored-by: Mit Parikh <mitparikh1046@gmail.com>
2026-07-17 16:58:21 +01:00
辛亥 34c5d006c3 fix(visualization): use #graph-svg selector instead of bare svg
d3.select("svg") returns the first <svg> in document order, which is a
16px legend icon — not the main graph canvas. This caused the entire
force graph to render inside the tiny legend swatch while the full-screen
canvas stayed empty.

Fix: target #graph-svg by id in both template copies. Add id="graph-svg"
to the aggregated-view template's <svg> element (it was missing).

Regression tests verify both full and community templates use the id
selector and contain no bare d3.select("svg").

Closes #523
2026-07-17 12:03:56 +01:00
Tirth Kanani ac658926d8 chore: resolve merge conflicts with main
Keep both sides: accessibility/ARIA/keyboard-nav from feat/accessibility-fixes
and community-legend CSS, community-legend HTML div, Phase 9 aggregation tests
from main. Node shapes use d3.symbol() path elements (accessibility PR wins
over main's circle approach) with aria-pressed on community toggle.
2026-05-07 10:26:53 +01:00
Tirth Kanani 440d75bf92 chore: release v2.3.2
15 new features: hub/bridge node detection, knowledge gap analysis,
surprise scoring, suggested questions, BFS/DFS traversal, edge
confidence scoring, export formats (GraphML/Neo4j/Obsidian/SVG),
graph diff, token benchmarking, memory loop, community auto-splitting,
4 new languages (Zig/PowerShell/Julia/Svelte), visualization
enhancements (degree-scaled nodes, community legend toggles).

6 community PRs merged: #127, #184, #202, #249, #253, #267.
28 MCP tools (was 22). Schema v9. 788 tests pass.

README translations: zh-CN, ja-JP, ko-KR, hi-IN.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 14:23:29 +01:00
Tirth Kanani e4e9f0a1b3 fix: 11 open bugs post-v2.2.3 (parser, ignores, fastmcp CVE, Windows, VS Code) (#222)
* fix: eval yaml guard + viz auto-collapse removal

- #212: eval runner.load_all_configs() now calls _require_yaml() before
  reading YAML, surfacing "install code-review-graph[eval]" instead of
  crashing with AttributeError on NoneType.safe_load when PyYAML isn't
  installed.
- #132: visualization.py no longer unconditionally auto-collapses every
  File node on startup; only kicks in at >2000 nodes. Previously, any
  graph >~300 nodes would hide all CALLS/IMPORTS/INHERITS edges because
  they connect Functions/Classes nested inside the collapsed Files.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(parser): Go receivers, Dart calls, inheritors_of fallback

- #190: Go method receivers — 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 (handling both T and *T forms).

- #87 bug 1 (Dart CALLS edges): tree-sitter-dart doesn't wrap calls
  in a call_expression; instead the pattern is identifier+selector
  where the selector contains argument_part. New
  _extract_dart_calls_from_children() walker handles both direct
  (print('x')) and method-chained (obj.foo()) shapes and emits CALLS
  edges with bare target names for the existing resolver.

- #87 bug 2 (Dart package: URIs): _do_resolve_module now handles
  "package:<name>/<path>" by walking up to a pubspec.yaml whose name:
  declaration matches <name>, then resolving to <root>/lib/<path>.
  Results are cached per (dir, pkg_name) pair.

- #87 bug 3 (inheritors_of bare-vs-qualified): query.py falls back to
  search_edges_by_target_name(node.name, kind="INHERITS"|"IMPLEMENTS")
  when the primary qualified-name lookup returns nothing. Mirrors the
  existing callers_of fallback; fixes not-just-Dart because bases are
  stored as bare strings for every language.

Tests:
- test_multilang.py TestGoParsing.test_methods_attached_to_receiver
- test_parser.py TestParserMultilang.test_parse_dart_call_edges

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: nested node_modules + framework ignores (#91)

_should_ignore() treated fnmatch patterns literally, so "node_modules/**"
matched only top-level "node_modules/*" and missed nested paths like
"packages/app/node_modules/react/index.js" in monorepos. For every
"<dir>/**" pattern that is a single bare segment we now also test
whether <dir> appears anywhere in the path's parts.

Extended DEFAULT_IGNORE_PATTERNS with ignores for:
- PHP/Laravel: vendor/**, bootstrap/cache/**, public/build/**
- Ruby/Bundler: .bundle/**
- Java/Kotlin/Gradle: .gradle/**, *.jar
- Dart/Flutter: .dart_tool/**, .pub-cache/**
- Generic: coverage/**, .cache/**

Note: intentionally did NOT add packages/** (false positive in yarn/pnpm
workspace monorepos) or bin/**/obj/** (false positive for legitimate
source dirs). Users can extend via .code-review-graphignore.

Tests: test_should_ignore_nested_dependency_dirs,
test_should_ignore_framework_defaults.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: replace bare 'except Exception' with specific handlers + logging (#194)

Each site caught Exception broadly and silently returned an empty default,
masking real bugs. Narrowed each to the actual expected exception classes
and added logger.debug() so failures are traceable:

- cli.py _get_version — PackageNotFoundError only
- eval/benchmarks/search_quality.py — ImportError, sqlite3.OperationalError
- graph.py get_all_community_ids / get_communities_raw — sqlite3.OperationalError
  (pre-v6 schemas lack community_id / communities table)
- migrations.py run_migrations — sqlite3.Error (re-raised after rollback+log)
- registry.py connection pool — sqlite3.Error
- tools/context.py — ImportError, OSError, ValueError, sqlite3.Error,
  subprocess.SubprocessError (risk analysis); sqlite3.OperationalError
  (missing communities/flows tables)
- tsconfig_resolver.py — OSError, ValueError, TypeError
- wiki.py — sqlite3.OperationalError

Tests continue to pass; no behavioral change at happy path.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: bump fastmcp to >=2.14.0, Windows SelectorEventLoop (#139, #195, #46, #136)

Three related problems, one dependency change + one line:

1. #139: fastmcp <2.14.0 has four published CVEs (CVE-2025-62800 XSS,
   CVE-2025-62801 command injection, CVE-2025-66416 Confused Deputy). We
   were pinned to "fastmcp>=0.1.0,<2" which resolved to fastmcp 1.0.
   Bumped to "fastmcp>=2.14.0,<3"; the public API (`FastMCP(name, ...)`,
   `@mcp.tool()`, `@mcp.prompt()`, `mcp.run(transport="stdio")`) is
   unchanged so no source edits needed beyond this pin. Verified all
   24 registered tools still resolve via mcp.get_tools() on 2.14.6.

2. #195: ImportError on FakeConnection/FakeRedisConnection. The chain
   was fastmcp 1.0 -> docket -> fakeredis; a recent fakeredis release
   renamed FakeConnection to FakeRedisConnection, breaking uvx installs
   at import time. fastmcp 2.x doesn't depend on docket/fakeredis at
   all, so bumping fixes this transitively.

3. #46 / #136: Windows build/embed hangs silently. On Python 3.8+ on
   Windows, asyncio defaults to ProactorEventLoop, which interacts
   poorly with ProcessPoolExecutor (used by full_build) over a stdio
   MCP transport — it deadlocks and the user sees "Synthesizing..."
   forever. main() now sets WindowsSelectorEventLoopPolicy before
   mcp.run() on win32 only. This is the well-known fix for the pattern
   and is a no-op on macOS/Linux. I cannot verify on Windows from
   macOS but the fix is surgical and the policy change has no other
   side effects.

uv.lock regenerated to drop docket/fakeredis and pick up fastmcp 2.14.6.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(vscode): better-sqlite3 12.x for Electron 39 / V8 14.2 (#218)

VS Code 1.115 ships Electron 39 / V8 14.2, which removed the
v8::Context::GetIsolate() C++ API used by better-sqlite3 11.x.  The
extension could not activate at all — every command was undefined
because ./dist/extension.js failed to require('better-sqlite3').

Bumped:
- better-sqlite3: ^11.0.0 -> ^12.4.1 (12.x uses the new V8 API and
  ships Electron 39 prebuilds). Currently installs 12.8.0.
- @types/better-sqlite3: ^7.6.8 -> ^7.6.13
- Extension version: 0.2.1 -> 0.2.2

src/backend/sqlite.ts: the @types/better-sqlite3 typings are still
"export =" style (CJS) but the type imports needed adjusting under
"module: Node16" strict mode:
- import type BetterSqlite3 from 'better-sqlite3' (via =require-style)
  then "type DatabaseType = BetterSqlite3.Database"
- Dropped the non-existent .default access on the imported namespace
- Dropped the "Database.Database" namespace reference in _db() return

Verified locally:
- npm install succeeds, 12.8.0 prebuild loads
- node -e "require('better-sqlite3')(':memory:').exec(...)" works
- npx tsc --noEmit passes
- node esbuild.mjs produces dist/extension.js at the same size

Long-term, node:sqlite (built-in to Node 22) would eliminate this
rebuild-per-Electron-version problem entirely, but that requires API
refactoring and is out of scope here.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 20:23:44 +01:00
Tirth Kanani 06570e489b fix: resolve CI failures on main — ruff lint + tomllib on Py3.10 (#220)
Main CI has been red for 13 consecutive pushes since #135. Root causes:

Lint job (ruff):
- skills.py: rename local vars _SCRIPT/_MARKER to lowercase (N806)
- communities.py: wrap long INSERT INTO SQL across two lines (E501)
- parser.py: strip trailing whitespace on Go field_identifier return (W291)
- visualization.py: rephrase comment so ruff stops parsing the embedded
  "# noqa: E501" reference as a directive

Test (3.10) job:
- tests/test_skills.py: tomllib is Python 3.11+ only. Use conditional
  import with tomli as the backport on 3.10.
- pyproject.toml: add "tomli>=2.0; python_version < '3.11'" to dev extras
- uv.lock: regenerated (also picks up pytest-cov + coverage entries that
  were already in pyproject.toml dev extras but missing from the lock)

Verified locally on Python 3.11:
- ruff check code_review_graph/ — All checks passed
- mypy code_review_graph/ — Success (44 source files)
- bandit -r code_review_graph/ — 0 issues
- pytest --cov-fail-under=65 — 661 passed, 1 skipped, 2 xpassed, 72.77% cov

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 18:02:05 +01:00
Tirth Kanani ea54fe663c feat: add community/file aggregation modes for large graph viz (Phase 9)
Add mode parameter to generate_html: "auto" (default), "full",
"community" (super-nodes by community), "file" (nodes by file).
Community mode supports double-click drill-down. CLI gets --mode flag.
Auto mode switches to community view above 3000 nodes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 14:11:04 +01:00
Tirth Kanani 6207a78943 design: style detail panel close button to match controls
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 14:07:13 +01:00
Tirth Kanani e7654d79a7 design: increase CONTAINS edge opacity from 0.08 to 0.14 for visibility
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 14:06:05 +01:00
Tirth Kanani 5a4ec554fb design: move detail panel to left side so it doesn't occlude controls
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 14:04:08 +01:00
Tirth Kanani 229dcfbbc2 feat: add help overlay with interaction guide to standalone HTML visualization
Expands the existing keyboard-shortcut overlay to include a full
interaction guide (click a file, shift-click, drag, scroll, etc.) and a
dismiss hint, so new users can discover the graph's interactions at a
glance. Adds a corresponding test.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 13:56:59 +01:00
Tirth Kanani 6bebe182c2 feat(a11y): edge differentiation, skip nav, focus styles, keyboard help overlay
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 13:54:23 +01:00
Tirth Kanani e661b2112b feat: complete node shapes + VS Code graph.ts changes for Tasks 1-3
Includes VS Code webview path rendering (SVGCircleElement -> SVGPathElement),
unified color palette in graph.ts, and symbolCross test assertion.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 13:52:39 +01:00
Tirth Kanani 1e129818d0 feat(a11y): add ARIA roles to tooltip, detail panel, legend, search results, communities button
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 13:40:27 +01:00
Tirth Kanani df801e5113 feat(a11y): add keyboard navigation for graph nodes (tab, arrows, enter, escape)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 13:34:52 +01:00
Tirth Kanani ec5c57dbc9 feat(a11y): use distinct d3.symbol shapes per node kind for colorblind users
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 13:31:10 +01:00
Tirth Kanani e94380be29 fix(a11y): improve text contrast ratios to meet WCAG 2.1 AA 4.5:1 minimum
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 13:24:03 +01:00
Tirth Kanani 3e98b9969e refactor: decompose parser + add GraphStore public API
Parser refactor (Finding 1.1):
- Break 386-line _extract_from_tree into 6 focused methods:
  _extract_r_constructs, _extract_classes, _extract_functions,
  _extract_imports, _extract_calls, _extract_solidity_constructs
- Main method reduced to ~72-line dispatcher
- Each method returns bool to control parent loop flow

GraphStore encapsulation (Finding 1.2):
- Add 17 public query methods to GraphStore: get_node_by_id,
  get_nodes_by_kind, count_flow_memberships, get_node_community_id,
  get_community_ids_by_qualified_names, get_files_matching,
  get_nodes_without_signature, update_node_signature,
  get_all_community_ids, get_node_ids_by_files,
  get_flow_ids_by_node_ids, get_flow_qualified_names,
  get_node_kind_by_id, get_all_call_targets, get_communities_list,
  get_community_member_qns, get_nodes_by_community_id,
  get_outgoing_targets, get_incoming_sources
- Update 8 caller modules to use public API instead of store._conn
- Remaining _conn usage documented in search.py, flows.py,
  communities.py for FTS5 DDL and batch write operations

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 19:00:41 +00:00
Tirth Kanani d1b8b82fec fix: batch of audit fixes — security, performance, quality
Quick fixes:
- Add explicit SSL context for MiniMax API calls (2.4)
- Add permissions: contents: read to CI workflow (2.5)
- Extract shared SECURITY_KEYWORDS to constants.py (3.2)
- Add error handling to watch mode on_deleted handler (4.4)
- Batch N+1 caller community lookups in risk scoring (4.6)
- Add large-graph warning in visualization (5.3)
- Migrate publish.yml to PyPI trusted publishing (2.3)

Medium fixes:
- Replace get_all_edges() with targeted IN-clause queries in wiki deps (5.1)
- Merge hybrid_search phases 3+4 into single batch fetch (5.2)
- Convert VSCode SqliteReader to async factory, remove busy-wait (4.5)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 18:19:19 +00:00
Tirth Kanani 85406cedb4 feat: v2.0 — 12 new features (flows, communities, hybrid search, refactoring, hints, prompts, skills, wiki, registry, eval, interactive viz)
* feat: add schema migration framework for v2 database evolution

Introduces a versioned migration system (v1-v5) that runs automatically
on GraphStore init, enabling incremental schema changes for flows,
communities, FTS5 search, and signature tracking.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: add transaction rollback to schema migrations

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: add missing indexes and clean up migrations

- Add CREATE INDEX statements in v3 migration (flows.criticality,
  flows.entry_point_id, flow_memberships.node_id)
- Add CREATE INDEX statements in v4 migration (nodes.community_id,
  communities.parent_id, communities.cohesion)
- Simplify redundant ternary in _table_exists to plain row[0] > 0
- Derive LATEST_VERSION from MIGRATIONS.keys() to stay in sync

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add execution flow detection, tracing, and criticality scoring

Implement flows.py with 7 functions: detect_entry_points (framework
decorators, name patterns, no-caller roots), trace_flows (BFS through
CALLS edges with cycle detection), compute_criticality (weighted scoring
on file spread, external calls, security sensitivity, test coverage gap,
depth), store_flows / get_flows / get_flow_by_id / get_affected_flows
for persistence and querying. Includes 19 tests covering all functions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: optimize entry point detection and tighten decorator patterns

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add flow MCP tools (list_flows, get_flow, get_affected_flows)

Wire the flows module into the MCP tool layer with 3 new tools:
- list_flows [EXPLORE]: list execution flows sorted by criticality
- get_flow [EXPLORE]: get detailed flow info with optional source snippets
- get_affected_flows [REVIEW]: find flows impacted by changed files

Registered all 3 as @mcp.tool() in main.py. Added TestFlowTools with
16 tests covering all tool functions, kind filtering, name search,
source inclusion, and affected flow detection.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: improve flow tool path handling and kind filter limit

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add community detection with Leiden algorithm and file-based fallback

Implement communities.py with detect_communities(), store_communities(),
get_communities(), and get_architecture_overview(). Uses igraph Leiden
algorithm when available, falls back to file-based grouping otherwise.
Includes auto-naming, cohesion scoring, sub-community splitting for
large clusters (>50 nodes), and cross-community coupling warnings.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: sanitize community names and clean internal state from outputs

Apply _sanitize_name to all community names, descriptions, member
qualified_names, and cross-community edge source/target returned to
MCP clients. Strip internal member_qns set from detect_communities()
return values to prevent leaking internal state.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add community MCP tools (list, get, architecture overview)

Wire community detection into MCP with 3 new tools:
- list_communities_tool: list detected code communities sorted by size/cohesion
- get_community_tool: get details of a single community by ID or name match
- get_architecture_overview_tool: high-level architecture view with coupling warnings

Includes 15 tests covering all tool functions, status codes, and edge cases.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add hybrid search engine with FTS5 + RRF fusion

Implement code_review_graph/search.py with:
- rebuild_fts_index: drops/recreates standalone FTS5 table from nodes
- hybrid_search: FTS5 BM25 + optional vector embeddings merged via
  Reciprocal Rank Fusion, with query-aware kind boosting (PascalCase
  boosts Class/Type, snake_case boosts Function, dotted paths boost
  qualified names) and context-file boosting
- rrf_merge: generic RRF implementation with configurable k parameter
- detect_query_kind_boost: heuristic query pattern detection
- Graceful fallback chain: hybrid -> FTS5-only -> keyword LIKE
- FTS5 injection prevention via double-quote wrapping

Update semantic_search_nodes in tools.py to use hybrid_search as its
primary search path with backward-compatible return format and new
optional context_files parameter.

20 tests covering index rebuild, FTS name/signature search, kind
boosting, RRF merge correctness, keyword fallback, empty queries,
field presence, kind filtering, context boosting, and injection safety.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add change impact analysis with risk-scored review guidance

Add changes.py module that maps git diffs to affected functions, flows,
communities, and test coverage gaps. Produces risk-scored (0-1),
priority-ordered review guidance. Register detect_changes_tool in MCP.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add graph-powered refactoring tools (rename, dead code, suggestions)

Add refactor.py module with rename_preview, find_dead_code,
suggest_refactorings, and apply_refactor operations. Register
consolidated refactor_tool and apply_refactor_tool as MCP tools
with path traversal prevention and 10-minute expiry enforcement.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add context-aware hints system for MCP tool responses

Introduce hints.py with SessionState tracking, intent inference from
tool-call history, and workflow-based next-step suggestions. Integrates
_hints into all new tool responses (tools 10-18 + semantic_search_nodes)
so Claude Code can suggest follow-up actions. Includes 19 tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add MCP prompt templates for guided workflows

Add 5 prompt functions (review_changes, architecture_map, debug_issue,
onboard_developer, pre_merge_check) that return structured message lists
for common code review workflows. Register all 5 via @mcp.prompt() in
main.py.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add Claude Code skills and hooks auto-install

Add skills.py with generate_skills (4 skill .md files), generate_hooks_config
(PostToolUse, SessionStart, PreCommit), install_hooks (.claude/settings.json),
and inject_claude_md (idempotent CLAUDE.md section). Add --skills, --hooks,
--all flags to the install/init CLI command.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add wiki generation from community structure (Task 12)

Generate markdown documentation pages for each detected code community,
with an index page linking them all. Includes overview, members table,
execution flows, and dependency sections per community page.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add multi-repo registry with connection pool (Task 13)

Add Registry class for managing multiple repos via ~/.code-review-graph/registry.json,
ConnectionPool with LRU eviction for SQLite connections, and cross-repo search.
Integrate wiki and registry tools into MCP server and CLI.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: interactive visualization upgrade and evaluation framework (Tasks 14-15)

Visualization: add flows/communities to export_graph_data, detail panel
on node click (callers/callees), community coloring toggle (D3 ordinal
scale), flow dropdown to highlight execution paths, search results
dropdown with zoom-to-node, and node kind filter checkboxes. Add --serve
flag to visualize command for local HTTP server on port 8765.

Eval framework: add scorer module with compute_token_efficiency,
compute_mrr, and compute_precision_recall. Add reporter module with
generate_markdown_report for benchmark results. Add eval CLI subcommand
(stub runner, working scorer/reporter).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: wire post-build steps and add detect-changes CLI command (Task 16)

After successful build/update, automatically compute node signatures,
rebuild FTS index, trace execution flows, and detect communities. Add
detect-changes CLI subcommand for risk-scored change impact analysis.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: bump version to 2.0.0 and add optional dependency groups (Task 17)

Add communities, eval, wiki, and all optional dependency groups to
pyproject.toml. Bump version from 1.8.4 to 2.0.0 for the v2 release.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: add comprehensive v2 pipeline integration test (Task 18)

End-to-end test exercising flows, communities, FTS search,
analyze_changes, find_dead_code, rename_preview, generate_hints,
review_changes_prompt, generate_wiki, and the Registry API.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: gitignore superpowers plans and specs directories

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: resolve mypy type errors and bandit security warnings

- Fix no-redef in registry.py (renamed shadowed variable)
- Add dict[str, object] annotations for hint-augmented results in tools.py
- Replace bare except/pass with logging in registry.py and visualization.py

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 14:26:01 +00:00
Tirth Kanani c8b000e526 fix: security and robustness hardening (#41)
- Add check_same_thread=False to EmbeddingStore SQLite connection
- Add _call_with_retry() with exponential backoff for Gemini API
- Escape </script> in visualization JSON (XSS defense)
- Split broad except into specific json.JSONDecodeError and (KeyError, TypeError)
- Add thread-safety comment on _default_repo_root in main.py
- Make git timeout configurable via CRG_GIT_TIMEOUT env var
- Expand test coverage: sanitize_name, find_large_functions, get_docs_section
- Clean up unused imports in test files

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 12:51:59 +00:00
Tirth Kanani a40ed5bab2 fix: detect test files, generate TESTED_BY edges, fix visualization stack overflow
- Set is_test=True on File nodes for test files (*.test.ts, *.spec.ts, etc.)
- Recognize JS/TS test-runner names (describe, it, test) in test files
- Generate TESTED_BY edges when test functions call production functions
- Convert recursive allDescendants to iterative (fixes #27 stack overflow
  on large codebases with 45k+ nodes)

Closes #21, Closes #27

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 11:11:48 +00:00
Tirth Kanani 1d7984f261 Merge pull request #8 from tirth8205/fix/visualization-xss
fix: escape quotes and backticks in escH to prevent stored XSS
2026-03-17 12:41:04 +00:00
Tirth Kanani da1f5535b8 fix: escape quotes and backticks in escH to prevent stored XSS
The escH function in the HTML template only escaped &, <, and >.
Node names containing quotes or backticks could inject scripts via
tooltip.innerHTML. Add escaping for ", ', and ` characters.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 12:30:36 +00:00
Tirth Kanani ba3a06f4e3 fix: add SRI hash to D3.js CDN script tag
Add integrity and crossorigin attributes to the D3.js script tag in
the HTML template to prevent supply-chain attacks if the CDN is
compromised.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 12:30:26 +00:00
Pat 8605803c1b fix: resolve C/C++ bare include paths in graph visualization (#4)
_build_name_index only indexed Python module-style paths, so
IMPORTS_FROM edges emitted as bare includes (e.g. "trading/Foo.hpp")
never matched File nodes stored with absolute paths. This left
C/C++ projects almost entirely disconnected in the visualization —
only 796 of 4300 edges were resolvable on a real project.

Fix: for every File node, also index all path suffixes
("Foo.hpp", "trading/Foo.hpp", "libs/trading/Foo.hpp", …) so that
any length of relative include path resolves to the correct node.

Adds a regression test with both a bare filename and a
relative-directory include path.

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-17 12:15:07 +00:00
Tirth Kanani 14554cf4ae fix: resolve all 24 audit issues across code, tests, docs, and CI
Critical fixes:
- Fix incremental hash comparison bug (file_hash field vs extra dict)
- Add GraphStore context manager (__enter__/__exit__)
- Add filtering to watch mode on_deleted handler
- Remove dead code in full_build and duplicate main()

Parser improvements:
- Add C/C++ support to all node type maps (class, function, import, call)
- Fix _get_name for Kotlin/Swift (simple_identifier), Ruby (constant)
- Handle nested function_declarator for C/C++ function names
- Add C++ inheritance via base_class_clause

Performance:
- Cache NetworkX graph in GraphStore with invalidation
- Batch edge collection in get_impact_radius (get_edges_among)
- Add subprocess timeout (30s) to all git calls
- Chunked embedding search (fetchmany 500)
- Replace MD5 with SHA-256 in embeddings

Tests:
- Add test_incremental.py (24 tests across 8 classes)
- Add test_embeddings.py (16 tests across 4 classes)
- Add 7 language fixture files (C, C++, C#, Ruby, PHP, Kotlin, Swift)
- Add multilang test classes for all new languages

CI:
- Add coverage enforcement (--cov-fail-under=50)
- Add bandit security scanning job
- Add mypy type checking job

Docs:
- Fix TROUBLESHOOTING.md hook config path
- Document default ignore patterns in USAGE.md
- Add API response schemas for all MCP tools in COMMANDS.md

Visualization:
- Replace private store._conn access with public get_all_edges()
- Add ARIA labels throughout (role, aria-label, aria-pressed)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 21:12:19 +00:00
Tirth Kanani e6c85ebc1f feat: v1.5.0 — file organization, visualization density, project cleanup
Move generated files into .code-review-graph/ directory with auto-created
.gitignore. Add visualization density features: collapsed start, search bar,
edge type toggles, scale-aware force layout. Remove redundant references/,
agents/, and settings.json. Update all docs and CHANGELOG for v1.5.0.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 23:33:10 +00:00
Tirth Kanani 263c17014f feat: add interactive D3.js graph visualization module
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 20:37:38 +00:00