Skip to content

Releases: sina-parsania/CodeGraph

v1.38.0

Choose a tag to compare

@github-actions github-actions released this 18 Jul 17:54

Full Changelog: v1.37.1...v1.38.0

v1.37.1 — rerank reaches the MCP

Choose a tag to compare

@sina-parsania sina-parsania released this 18 Jul 16:36

1.37.1 — rerank reaches the MCP

search (MCP) gains an optional rerank parameter — same local-LLM
reordering the CLI's --rerank had (config rerank = true /
CODEGRAPH_RERANK=1 for the CLI default). The implementation moved to
codegraph-llm so both surfaces share one function; the LLM call runs on
spawn_blocking (the embedder-probe wedge class stays impossible), and it
degrades to the original order when no local model answers.

v1.37.0 — lean MCP payloads, semantic that can't dead-end, MCP↔CLI parity

Choose a tag to compare

@sina-parsania sina-parsania released this 18 Jul 15:19

1.37.0 — lean MCP payloads, semantic that can't dead-end, MCP↔CLI parity

Driven by the third field report (v1.36 head-to-head vs ripgrep on a 5-project
monorepo — structural queries won; three defects found, all fixed).

  • MCP routes was unusable by its own client (232 KB single-line JSON,
    rejected by Claude Code)
    : each route serialized the FULL graph node.
    Now: lean rows ({method, path, handler, file, line}) + limit/offset
    pagination + path_prefix/method filters; 560 routes ≈ 6 KB. Same lean
    sweep applied to every list-shaped MCP response that still leaked full
    nodes: implementers, dead_code, pinned callers. One shared lean
    serializer; full node detail stays behind get_node(id).
  • semantic_search can no longer dead-end: with no embedder it degrades
    to lexical search and says so ("degraded": "lexical fallback — no embedder…") instead of hard-failing a tool it advertised. stats reports
    embedder_available up front so agents route around it. install.sh now
    builds with local-embed (bundled bge-small) by default — and
    indexstore on macOS — so the stock install answers semantic queries out
    of the box. CODEGRAPH_NO_EMBEDDER=1 forces lexical-only (also the
    deterministic test hook).
  • MCP↔CLI naming parity: semantic-search/semantic_search
    semantic, blast-radius/blast_radiusimpact,
    trace-path/trace_pathtrace, graph-query/graph_query
    cypher, dead_codedead-code (joins the earlier statsstatus).
    Agents translate MCP names to CLI constantly; every advertised name now
    resolves.
  • Regression tests: routes payload cap (<25 KB on 300 routes) + pagination +
    filters, alias resolution for every MCP name, forced no-embedder
    degradation with embedder_available:false in stats.

v1.36.0 — speed where it's visible + every fix is a release gate

Choose a tag to compare

@sina-parsania sina-parsania released this 18 Jul 13:22

1.36.0 — speed where it's visible + every fix is now a release gate

Driven by the second field report ("we should be 10–20× faster than grep,
we're tied"): the tie was the freshness probe, not the answer.

  • Probe parallelized: the two root git ls-files spawn concurrently,
    nested-repo enumerations fan out on rayon, and the 8k-file stat sweep is
    parallel. Default-path query on an 8.7k-file monorepo: 0.21 s → 0.10 s —
    vs rg's 0.21 s without any freshness guarantee. Warm path (--no-autoheal
    / MCP between heals): 0.00–0.02 s — 10–100× rg. The honest framing: rg
    pays full scan per query; codegraph pays a freshness proof once and ~0
    after.
  • Constant-path routes recovered: @Delete(SOME_CONST) endpoints are
    real — they now emit with the constant as a «symbolic» segment +
    path_unresolved: true instead of being dropped (66 real endpoints on the
    field monorepo; route accounting now closes exactly: 524 decorators =
    458 literal/bare + 66 symbolic).
  • --indexstore early-return bug: with zero file changes the flag never
    reached the merge path — a re-merge no-op'ed. Fixed; field monorepo now
    carries a 46,110-edge Swift compiler oracle and codegraph audit measures
    96.1% precision (SelfThisMember 100%, SameFileUnique 96.6%,
    FieldTypeMember 83.3% on a small sample) — served via MCP stats.
  • codegraph stats aliases status (agents guess the MCP tool name).
  • Doc noise capped: identifier search keeps docs to ≤5 rows (one per
    file) when code answered the query.
  • Release gate: scripts/release-qa.sh runs clippy-clean, the full
    suite, crash-recovery + determinism e2e, and the eval receipts — every
    field-reported bug fixed in 1.34–1.36 has a pinned regression test
    (enumeration classes, flock exclusion, MCP empty-graph/dead-root/
    generation-bump, --files machine contract, NestJS route shapes, DI
    narrowing, search ranking).

v1.35.0 — field-test fixes: the MCP can't lie, NestJS answers

Choose a tag to compare

@sina-parsania sina-parsania released this 18 Jul 08:32

1.35.0 — field-test fixes: the MCP can't lie, NestJS answers

Driven by a promom field-test report (11.6k files, TS+Swift+Python) that
found two red bugs and three weaknesses. All fixed, all regression-tested.

  • MCP empty-graph bug (red): codegraph init wired the USER-GLOBAL MCP
    registration with one repo's absolute --path — the last-initialized repo
    won globally, and when that repo moved every project got a confidently
    empty graph ("no callers", nodes: 0) while the CLI was healthy. Fixed
    three-deep: registration is now cwd-following (no --path); a dead root
    refuses to serve at startup; and an EMPTY graph refuses to answer at all —
    every tool returns a diagnosis instead of clean emptiness (stats stays
    reachable and reports EMPTY_GRAPH). Regression suite proves a generation
    bump under a running server is served fresh on the next call.
  • NestJS routes (red): decorator routes (@Get(':id'), bare @Get())
    never matched the leading-/ requirement, and @Controller('prefix') was
    never joined (including the @Controller(…)\nexport class shape where the
    decorator hangs off the export_statement). e2e/spec files polluted the
    answer with test traffic. Object-form @Controller({ path: 'x', … }) is
    read too, and a constant path (@Delete(SOME_CONST)) is skipped instead of
    fabricating "/" — a made-up path is a wrong answer, not a route. promom:
    120 noisy routes → 494 fully-prefixed real ones, zero spec noise, zero
    fabricated paths.
  • TS DI caller resolution (was ~0%): this.profileService.getUserProfile()
    with constructor(private readonly profileService: ProfileService) never
    resolved when the class NAME exists in two apps of a monorepo (global
    unique-or-drop). The caller file's import now disambiguates the type —
    same evidence class as ImportNarrowed, unique-or-drop preserved. promom:
    0/23 → fully resolved caller list (+465 edges). Swift resolution untouched
    (its tests pin the behavior).
  • search noise: identifier search ranks ANY code symbol above Document
    fragments, and collapses doc hits to one row per file.
  • stale audit: stats no longer serves an outdated audit under
    measured_precision — stale numbers move to stale_audit_not_current.
  • index lock → OS flock (std File::try_lock, Rust 1.89 — zero deps):
    the kernel releases the lock the instant the owner dies, so the PID-stamp /
    dead-owner-steal machinery from 1.34 is deleted outright. Measured: kill -9
    mid-index → next query self-heals and answers in 69 ms.
  • callers --files: unpinned name-level questions return the UNION across
    same-name definitions again (dominant-definition narrowing was a measured
    recall loss), definition files stay as labeled evidence, human notes moved
    to stderr. Eval receipts (SCIP ground truth, 68 questions): P 0.66 /
    R 0.98 / answer-rate 100% / 319 B
    vs grep 0.63 / 0.94 / 100% / 2,701 B —
    ahead of grep on every measured dimension. (The 1.33 "R 0.87" receipt was
    stale: the harness predated the v1.33 --files format.)

v1.34.0 — zero-false-negative enumeration + ops hardening

Choose a tag to compare

@sina-parsania sina-parsania released this 17 Jul 15:16

1.34.0 — zero-false-negative enumeration + ops hardening

Enumeration moved from directory-walking to git ls-files (tracked +
untracked-unignored), with the walker as fallback. This is not just faster —
it is MORE COMPLETE: git knows which files are tracked, and tracked beats
gitignore. Measured on a live monorepo: 26 real docs (SRS, bug
investigations) lived under a docs/* ignore pattern but were committed
anyway — the walker dropped them forever, the git tier indexes them.
Staleness probe on a 3.6k-file repo: no-op index 0.19s.

  • Nested plain repos (monorepo of independent .git checkouts, no
    .gitmodules): ls-files silently skips their subtrees — untracked dirs
    carrying a .git are enumerated recursively; any level that can't take
    the git path falls the whole enumeration back to the walker.
  • .codegraphignore applied on the git listing (root-level, cascades
    into nested repos) — no more walker fallback just because the file exists.
    Submodules (.gitmodules) still force the walker: dropping submodule
    symbols would be a false negative.
  • Walker parity: hidden(false) — dot-dirs carry real content
    (.claude/ agent docs, .github/), and git enumerates them; junk
    dot-dirs stay excluded via EXCLUDE_DIRS.
  • Engine-version gate: the rebuild stamp now includes the release
    version alongside PARSER_VERSION — every upgraded binary rebuilds
    automatically; a resolver change nobody remembered to stamp can no longer
    serve a stale-engine graph.
  • Cross-process index lock: MCP server, its watcher thread, and parallel
    CLI runs serialize on a PID-stamped lock file; dead owners are stolen
    instantly (kill -0 liveness + stale-age window), so a kill -9 mid-index
    never bricks the next query — verified live: the orphaned lock was stolen
    by the very next search, which self-healed and answered.
  • Binary sniff: a NUL byte in the first 8KB (generated blobs with code
    extensions — valid UTF-8) keeps the file manifested but contributes zero
    symbols.
  • Ambiguous-candidate ranking (MCP callers): strongest resolved evidence
    first, cross-language ties broken toward the language family the textual
    evidence lives in. Ranking only — never changes which edges exist.
  • CODEGRAPH_MCP_CONCISE=1: drops per-response coaching fields
    (_hints, explainer notes); coverage/_fallback/truncation notes always
    stay. Measured 265→166 B on a callers answer.

Receipts: branch-switch storm (150 files) heals partially in 0.12s with
exactly reversible node counts; git-vs-walker parity proven on an identical
tree (1200 == 1200 nodes); verify-determinism byte-identical on a 3.6k-file
repo; zero phantom edges on 71k- and 25k-edge live graphs.

v1.33.1

Choose a tag to compare

@github-actions github-actions released this 11 Jul 17:24

Full Changelog: v1.33.0...v1.33.1

v1.33.0

Choose a tag to compare

@github-actions github-actions released this 11 Jul 17:11

Full Changelog: v1.32.0...v1.33.0

v1.32.0

Choose a tag to compare

@github-actions github-actions released this 11 Jul 14:07

Full Changelog: v1.31.1...v1.32.0

v1.31.1

Choose a tag to compare

@github-actions github-actions released this 11 Jul 12:21

Full Changelog: v1.31.0...v1.31.1