Skip to content

v3.16.0

Latest

Choose a tag to compare

@carlos-alm carlos-alm released this 17 Jul 09:02
2e0e94f

Remote embedding providers, complexity metrics for six more languages, and a broad resolver/extractor accuracy sweep across both engines. codegraph embed and codegraph search can now call a self-hosted or third-party OpenAI-compatible /embeddings endpoint instead of only the bundled local model, configured via a new embeddings.provider setting. codegraph complexity gains cognitive/cyclomatic/Halstead metrics for C, C++, Kotlin, Swift, Scala, and Bash on the WASM engine, which previously returned nothing for these languages. The Leiden community-detection algorithm is now ported to native Rust, closing a long-standing engine-parity gap where native ran classic Louvain while WASM ran Leiden. codegraph watch's incremental rebuild path gains CHA/RTA virtual-dispatch, points-to fallback, and dynamic-sink edge emission that only full builds previously produced, and reverse-dependency edge reconnection is fixed for a compound sibling-count-and-line-shift edge case. Deleted-file export tracking is now durable across purge ordering, so codegraph check's signature-change gate can no longer be bypassed by rebuild timing. Beyond these headline items, over a hundred targeted fixes improve call-edge resolution, symbol extraction, and native/WASM parity across nearly every supported language.

Features

  • search: configurable remote embedding provider — set embeddings.provider: "openai" and llm.baseUrl in .codegraphrc.json to route codegraph embed through any OpenAI-compatible /embeddings endpoint (self-hosted text-embeddings-inference, Ollama, LM Studio, vLLM, or OpenAI itself); codegraph search and the semantic_search MCP tool embed queries through the same remote provider; new CODEGRAPH_LLM_BASE_URL env override; reuses the existing llm.apiKey/apiKeyCommand secret resolution (#1716)

Bug Fixes

  • check: persist a durable snapshot of each deleted file's exported symbols and external consumers (new deleted_export_advisories table, mirrored in the native orchestrator) so the no-signature-change gate can't be bypassed depending on whether check runs before or after a rebuild has already purged the deleted file's rows (#1939, #2103)
  • incremental: port CHA/RTA virtual-dispatch, points-to/alias fallback, and dynamic-sink edge emission into codegraph watch's single-file rebuild path — these three edge categories were silently absent whenever a file was rebuilt via watch mode instead of a full build (#1997)
  • native: port the Leiden algorithm to Rust so both engines run the identical community-detection implementation, closing a documented "intentional" engine mismatch where native ran classic Louvain and WASM ran Leiden (#1937)
  • incremental: fix reverse-dependency edge reconnection when a same-named sibling group's size changes in the same edit as a line shift — replaces the ordinal/nearest-line heuristic with alignment by the dominant shift that best explains surviving siblings (#2014)
  • complexity: add cognitive/cyclomatic/Halstead rule support for C, C++, Kotlin, Swift, Scala, and Bash to the WASM engine, which previously had no rules at all for these languages; also fixes three native-only rule bugs surfaced during the port (C/C++ else-clause detection, Bash trailing-else scoring, Swift logical-operator node types) and a WASM-only double-counting bug for node types shared between branch and case sets (#2059)
  • complexity: stop using dotted names as a proxy for signature-only stubs; scope summary stats to file/target/kind filters; recognize Lua function nodes in complexity computation (#2056, #1953, #1924)
  • resolver: attribute new ClassName() calls to the constructor method, kind-filter same-file bare-name lookup for receiver-bearing calls, recognize identifier arguments passed to user-defined higher-order functions via parameter type, require invocation evidence for object-literal value-ref liveness, pick the single best match in resolveByGlobal instead of every candidate, and scope extends/implements edges to same-file/import/language candidates (#2028, #2026, #1989, #2034, #2000, #1957)
  • extractors: extract bare super(...) constructor calls as call edges, extract rest/default bindings from dynamic import() destructures, emit per-element definitions for array-pattern destructuring, resolve inline object-literal dispatch tables on WASM, attribute same-file ES6 getter/setter property reads as call edges, capture top-level const definitions regardless of initializer shape, align native/WASM definition order for object-literal methods, and label property_signature interface/type members with kind property (#2102, #2052, #2038, #2035, #2031, #1964, #1963, #1955)
  • native: resolve monorepo workspace package imports, add an Object.defineProperty accessor dispatch post-pass to the native orchestrator, scope barrel-only import skipping to transient barrel re-parses, propagate edge/node write failures out of run_pipeline instead of swallowing them, write dynamic_kind for sink edges, recover renamed import names in the FFI hybrid import-edge path, and resolve self.field/unit-struct/constructor-typed locals (#2061, #2024, #1991, #1972, #1698)
  • dynamic-calls: port Lua eval/computed-key dynamic-call detection to the WASM extractor; restore reflection dynamicKind for .call/.apply/.bind; gate identifier-argument dynamic call edges on callback-accepting callees; apply the plain-identifier guard to the query path for .call/.apply/.bind (#2043, #1917, #1846, #1697)
  • roles: exclude genuine class/struct properties from dead-role classification; restrict entry-role classification to function/method-kind symbols; attribute liveness to Lua functions assigned to global/builtin identifiers (#1956, #1919, #1912)
  • exports: credit plain imports of TypeScript interfaces/type aliases, discriminate file-level from symbol-level consumer entries, credit instanceof ClassName checks, and credit destructured dynamic import() bindings as consumers (#1978, #1974, #1930, #1921)
  • cycles: classify cycles whose only closing edges are speculative (#1988)
  • incremental: correct blast-radius/fn-impact computation for line-shifted declarations, add a same-class bare-call fallback, recompute directory structure metrics for affected directories, couple file_hashes updates with edge regeneration, scope neighbor expansion to the changed file, and eliminate non-deterministic ordering in community detection (#1916, #1886, #1840, #1828, #1950, #1835)
  • db: derive loadConfig() rootDir from the --db path in read-only query functions, thread configured busyTimeoutMs into NativeDatabase open factories and remaining read-only query call sites, resolve directory paths in findDbPath to .codegraph/graph.db, resolve codegraph embed's default DB path from the positional dir instead of cwd, and log (instead of silently swallowing) statSync failures in findDbPath (#2018, #2021, #1943, #1706, #1869, #1903)
  • config: derive ENV_LLM_KEYS from ENV_LLM_MAP to prevent drift; wrap remote embedding JSON parse failures in EngineError; scaffold an embeddings section in config --init (#1998, #1854, #1719)
  • quality: fix a config-mutation bug where applyExcludeTestsShorthand corrupted the shared DEFAULTS.query object for the rest of a long-running process (e.g. codegraph mcp --multi-repo); fix a resource-leak ordering bug in openReadonlyWithNative that could leak an open SQLite handle on a config error; fix a merge() aliasing bug in the graph model, found and fixed across builder, resolver, search, ast-analysis, presentation, extractors, and CLI modules during a broader Titan-audit quality sweep (#1788, #1789, #1790)
  • ast: exclude PHP scalar type-hint/cast keywords and primitive type keywords from ast --kind string matching (#1965, #1822)
  • extractors: classify destructured bindings as constant not function; emit reference edges for function identifiers used as object-literal values; replace the fixed-depth directory-proximity check with symmetric distance; track inline per-specifier type-only import modifiers; track barrel re-export renames (export { X as Y } from ...); record the local alias for dynamic import() destructuring renames; resolve renamed-import receiver calls in qualified-method lookup (#1902, #1898, #1894, #1958, #1968, #1970, #1971)
  • check/analysis: gate the blast-radius check on newly introduced risk rather than pre-existing fan-in; compare signature-change diffs using new-file line ranges; correct exported-symbol detection for literal and object-literal exports; scope reexportedSymbols to actually-named re-export specifiers; stop CFG block/edge counts from overriding AST-derived cyclomatic complexity; unify Object.defineProperty accessor fallback kind-filtering between build paths; prevent an fn-impact/query crash when -f/--file is passed; scope codegraph batch complexity targets to file paths; scope signature-change detection to exported symbols; scope diff file-header detection to between-hunk positions; scope the global call-resolution fallback to same-language candidates (#1843, #1829, #1820, #1849, #1851, #1889, #1816, #1808, #1792, #1940, #1928)
  • search: skip auto-install when the embed target is npm's own global root (#1722)
  • tracer: preserve target file permissions and surface copy failures in sedi(), fix C/C++ dynamic tracer compile/link/crash bugs, fix BSD-incompatible sed injection at remaining JVM/native call sites, and add a main.rs driver to the Rust dynamic tracer fixture (#2097, #2050, #2047, #1935)
  • hooks: skip edit-log validation for in-progress merge commits, point update-graph.sh's fallback build path at dist/cli.js, resolve track-edits.sh's PROJECT_DIR from the edited file's path, and sync update-graph.sh's extension allowlist with EXTENSIONS (#2100, #1980, #1982, #1837)
  • ci: skip automated Claude review for trivial/docs-only PRs, skip native-host-build when no native-relevant paths changed, allow-list Publish trigger events in benchmark.yml instead of excluding push, extract a reusable workflow for the native cross-compilation matrix, and move dev builds from every push to a daily schedule (#2117, #2116, #2114, #2115, #2113)
  • bench: anchor KNOWN_REGRESSIONS staleness to the recorded baseline, apply the sink-edge exclusion filter to scripts/resolution-benchmark.ts, resolve benchmark hub targets to a single kind-filtered node, resolve token-benchmark.ts --perf imports to real nested module paths, and exempt 3.15.0 baseline drift for the "Full build / 1-file rebuild" gate (#1704, #1699, #2039, #2041, #2107)
  • housekeep/sweep: make the orphaned-worktree loop zsh-safe; mine the Greptile summary body for findings, not just inline comments (#1714, #1707)
  • titan: verify embeddings per-worktree instead of trusting a stale state flag; update titan-grind's dead-symbol script for the current roles --json object shape (#1805, #1942)
  • scripts: migrate ts-resolve-loader.js off the deprecated module.register() API
  • test: accept the ts-native technique in the issue-1292 pts test (#1696)
  • perf: resolve config once in withRepo to avoid a double loadConfig() call (#2104)

Performance

  • native: fix a full-build regression in the P6 dataflow vertex pass (#1700)

Refactors

  • db/config: decompose findDbPath/openRepo, loadConfig, and token-benchmark.ts's runPerfBenchmarks/runSession; extract a shared platform-default-path helper and shared CFG/complexity result-merging into apply-results.ts (#1859, #1858, #1908, #2040, #1856, #1992)
  • builder: decompose extractors, build-edges, native-orchestrator, and remote.ts; extract shared leiden/config/builder/feature abstractions; share a chunked statement-cache primitive between builder and structure; cache prepared statements in the edge-technique post-insert chunk loop (#1787, #1786, #1890, #1891)
  • cli: unify call-ref/tests rendering between audit and inspect, and impact-level rendering between audit and fn-impact; widen outputResult's signature to remove redundant casts at call sites (#1900, #1931, #1933)
  • misc: dedupe busy/locked error detection into isBusyOrLockedError; register hardcoded execFileSync/execSync maxBuffer values in DEFAULTS; remove unreachable Partition delta-computation interface methods; route domain/search console logging through the logger; reduce cyclomatic complexity of computeDeltaModularityDirected and leiden's makePartition; extract a shared sedi() helper for tracer scripts; dedupe computeSavings via a pct helper and persist partial token-benchmark results (#1899, #1841, #1896, #1870, #1925, #1915, #1934)

Chores

  • docs: fix stale codegraph check flag names in recommended-practices.md; refresh CONTRIBUTING.md for the current TypeScript architecture and tooling; correct hasActiveFileSiblings JSDoc to match population logic; regenerate stale audit/diff-impact example output blocks; add the missing titan-grind mirror to claude-code-skills examples (#1986, #1977, #2044)
  • infra: add an environment doctor check (npm run doctor, npm run doctor -- --fix) that diagnoses a stale native binary or incomplete WASM grammars per-worktree, wired as a report-only pretest step; gitignore __pycache__ directories (#1834, #1717)
  • deps: bump web-tree-sitter/tree-sitter-cli to 0.26.10, @biomejs/biome to 2.5.3, @commitlint/cli/@commitlint/config-conventional to 21.2.1, vitest/@vitest/coverage-v8 to 4.1.10, actions/cache to 6, and anthropics/claude-code-action to 1.0.171 (#1708, #1709, #1710, #1711, #1712, #1796, #1797, #1798, #1799, #1800, #1801, #2090, #2091, #2092, #2094, #2095)