Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 25 additions & 10 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,41 @@ Protocol) stdio server. No AI / vector / LLM anywhere in the binary — output i
`crates/codegraph-bench/fixtures/python/`; guards six bare class-as-value
`References` edges — return, assignment RHS, registry pair, call argument,
list literal, and one cross-file unique match — plus tuple-return and bare-method
negatives, byte-for-byte), `reference/golden/kotlin/` (corpus
negatives, plus #1626 Python module/member import aliases and their no-global-fallback
boundaries, byte-for-byte), `reference/golden/kotlin/` (corpus
`crates/codegraph-bench/fixtures/kotlin/`; guards #1495 Kotlin callable
signatures for explicit, inferred, generic, multiline nullable, and extension
returns, plus a primary-constructor negative — byte-for-byte),
`reference/golden/typescript/` (corpus `crates/codegraph-bench/fixtures/typescript/`;
guards #1482 local export aliases and #1482b TypeScript `.js`-specifier
substitution, including TS-over-JS collision precedence — byte-for-byte), and
substitution, object-literal callable members, inherited/config-relative TS
path aliases, and `.xsjs`/`.xsjslib` import candidates with ordinary-JS
precedence — byte-for-byte), and
`reference/golden/cpp/`
(corpus `crates/codegraph-bench/fixtures/cpp/`; guards #1043 C++ class/struct
inheritance incl. templated-base stripping byte-for-byte, and retroactively
the earlier C++ extraction work; grown to 17 files by Tier 3 with the MSVC COM
the earlier C++ extraction work; grown to 19 files with full-source lexically
masked plain-derived `.h` detection and its text/bitfield/label/ternary
negatives, plus the Tier 3 MSVC COM
`interface` positives + five guard negatives (#1519) and the C / C++ / ObjC
`union` fixtures incl. both `typedef union` re-kinds and both instantiation
paths (PR #1516) — it is the C-FAMILY corpus, not a strictly-C++ one, since it
holds `.c` and `.mm` files too), and `reference/golden/rust/`
(corpus `crates/codegraph-bench/fixtures/rust/`; the repo's only Rust corpus,
(four-file corpus `crates/codegraph-bench/fixtures/rust/`; the repo's only Rust corpus,
guards #1513/PR #1514 unit structs — 3 `struct` nodes and 4 `implements` edges,
where the unit struct produced NO node before — plus the Rust half of PR #1516's
first-class `union` kind, byte-for-byte; it deliberately claims NO `instantiates`
edge, because that edge fires only for the call-expression construction form and
a Rust union is constructible only as `U { … }`), and `reference/golden/go/`
first-class `union` kind, generic/lifetime/reference/qualified impl ownership,
and the statically safe subset of `self.field.method()` resolution, byte-for-byte;
it deliberately claims NO `instantiates` edge, because that edge fires only for
the call-expression construction form and a Rust union is constructible only as
`U { … }`), `reference/golden/lua/` (single-file corpus
`crates/codegraph-bench/fixtures/lua/`; guards #1616 local/table-field function
expressions, nested qualified names, body-call ownership, dot/colon calls, and
dynamic-key negatives — byte-for-byte), `reference/golden/erlang/` (seven-file
corpus `crates/codegraph-bench/fixtures/erlang/`; guards bare display names plus
`module::function/arity` identity across clauses, exports, specs, local/remote
calls, fun values, safe MFA dispatch, and binary-literal comma counting —
byte-for-byte), and `reference/golden/go/`
(corpus `crates/codegraph-bench/fixtures/go/`; the repo's only Go corpus, and the
only corpus where `files.generated` is anything other than `0` — it byte-pins
#1500 content-header detection at BOTH values, three each way: `payroll.go`
Expand All @@ -52,9 +66,10 @@ Protocol) stdio server. No AI / vector / LLM anywhere in the binary — output i
import Gate 3b is deliberately unreachable for real Python nodes because the
extractor does not mark them exported. Regen recipe: `docs/equivalence.md`
"Godot fixture" / "Ruby fixture" / "Python fixture" / "Kotlin fixture" /
"TypeScript resolution fixture" / "C++ fixture" / "Rust fixture" / "Go fixture"
sections. `mini` has no re-indexable provenance and a schema migration cannot
normalise it in place, so it has its own "Mini schema rebuild" recipe there.
"TypeScript resolution fixture" / "C++ fixture" / "Rust fixture" / "Lua fixture" /
"Erlang fixture" / "Go fixture" sections. `mini` has no re-indexable provenance
and a schema migration cannot normalise it in place, so it has its own
"Mini schema rebuild" recipe there.
- **node-id formula**: `{kind}:{sha256("{filePath}:{kind}:{name}:{line}").hex[:32]}`; file nodes are the
literal `file:{relpath}`; lines are 1-based; paths relative with `/`.
- **No AI / vector / LLM crates** — enforced by `scripts/guardrail.sh` (CI gate):
Expand Down
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,11 @@ Set `CODEGRAPH_NO_DAEMON=1` to force foreground mode (useful in CI). The daemon
watches files with a 2 s debounce; pass `--no-watch` or set `CODEGRAPH_NO_WATCH=1`
to disable. Custom extension mapping goes in `.codegraph/codegraph.json`;
exclude patterns in `.codegraph/config.toml` under `[indexing] exclude`.
Changes to those two files, or to the project-root `.gitignore`, hot-reload the
running watcher and trigger one full reconcile. Newly excluded files are removed
and newly included/custom-extension files are added without restarting the MCP
server. Invalid TOML keeps the last valid watcher scope and reports the error;
malformed JSON keeps the existing tolerant empty-override behavior.

Full env-var table, HTTP server details, filesystem fallback behavior, and the
Claude prompt-hook: [`docs/mcp.md`](docs/mcp.md) and
Expand Down Expand Up @@ -478,6 +483,15 @@ graph for that file, and does not stop other files from being indexed. Increment
`sync` removes any older graph for the failed file and converges with
`index --force`.

Graph correctness includes Erlang `module::function/arity` identity, Rust
generic/reference/qualified `impl` ownership and validated
`self.field.method()` calls, JavaScript-family object-literal namespace members,
inherited TypeScript/JavaScript path aliases, Python import aliases, Lua
function-expression callables, extensionless `.xsjs`/`.xsjslib` imports, and
plain derived C++ classes/structs in `.h` files. See
[`docs/languages.md`](docs/languages.md) for the exact static-analysis
boundaries.

**Doesn't:** no AI / vector / embedding / LLM anywhere inside the binary (hard
constraint, `scripts/guardrail.sh`-enforced); no semantic search; no languages
beyond the fixed `LANGUAGES` set.
Expand Down
12 changes: 12 additions & 0 deletions crates/codegraph-bench/fixtures/cpp/plain_derived.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#pragma once

#include "base.hpp"

class HeaderDerived : public Base {
};

struct HeaderTemplateDerived : protected virtual ns::Tpl<int> {
};

class HeaderQualifiedDerived : private ns::Tpl<long> {
};
18 changes: 18 additions & 0 deletions crates/codegraph-bench/fixtures/cpp/plain_header_negatives.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#pragma once

struct HeaderBits {
unsigned enabled : 1;
};

static inline int choose_value(int flag)
{
label:
return flag ? 1 : 0;
}

static const char *header_text = "class HeaderGhost : HeaderBits";

/*
struct HeaderCommentGhost : HeaderBits {
};
*/
11 changes: 11 additions & 0 deletions crates/codegraph-bench/fixtures/erlang/client.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
-module(client).
-export([fetch/1, broken/1, mapper/1]).

fetch(Key) ->
store:get(Key, nil).

broken(Key) ->
store:get(Key, nil, extra).

mapper(Values) ->
lists:map(fun store:get/1, Values).
13 changes: 13 additions & 0 deletions crates/codegraph-bench/fixtures/erlang/deleg.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
-module(deleg).
-export([header/2, header/3, binary_arg/1]).

-spec header(binary(), map()) -> any().
header(Name, Req) ->
header(Name, Req, undefined).

-spec header(binary(), map(), any()) -> any().
header(Name, Headers, Default) ->
maps:get(Name, Headers, Default).

binary_arg(<<Name, Value>>) ->
header(Name, #{value => Value}).
8 changes: 8 additions & 0 deletions crates/codegraph-bench/fixtures/erlang/multi.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-module(multi).
-export([job/1, job/2]).

job(Value) ->
Value.

job(Left, Right) ->
{Left, Right}.
5 changes: 5 additions & 0 deletions crates/codegraph-bench/fixtures/erlang/single.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-module(single).
-export([work/1]).

work(Value) ->
Value.
6 changes: 6 additions & 0 deletions crates/codegraph-bench/fixtures/erlang/spawner.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
-module(spawner).
-export([go/1]).

go(Args) ->
erlang:spawn(single, work, Args),
erlang:spawn(multi, job, Args).
8 changes: 8 additions & 0 deletions crates/codegraph-bench/fixtures/erlang/store.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-module(store).
-export([get/1, get/2]).

get(Key) ->
get(Key, undefined).

get(Key, Default) ->
{Key, Default}.
35 changes: 35 additions & 0 deletions crates/codegraph-bench/fixtures/lua/handlers.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
local function helper()
return 1
end

local localFn = function()
return helper()
end

local M = {
callbacks = {
onStart = function()
return helper()
end,
["onStop"] = function()
return helper()
end,
[DYNAMIC] = function()
return helper()
end,
},
}

M.assignedFn = function()
return helper()
end

M["bracketFn"] = function()
return helper()
end

localFn()
M.assignedFn()
M:assignedFn()

return M
15 changes: 15 additions & 0 deletions crates/codegraph-bench/fixtures/python/aliases.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from pkg import module as mod_alias
import top_level as tl
from imported_types import ImportedClass as ImportedAlias


def from_import_caller():
return mod_alias.func()


def plain_import_caller():
return tl.top_func()


def member_alias_value():
return ImportedAlias
1 change: 1 addition & 0 deletions crates/codegraph-bench/fixtures/python/pkg/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Package marker for module-alias resolution fixtures."""
2 changes: 2 additions & 0 deletions crates/codegraph-bench/fixtures/python/pkg/module.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
def func():
return 1
2 changes: 2 additions & 0 deletions crates/codegraph-bench/fixtures/python/top_level.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
def top_func():
return 2
95 changes: 95 additions & 0 deletions crates/codegraph-bench/fixtures/rust/impl_ownership.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
pub trait Source {
fn read(&mut self) -> usize;
}

pub struct FileSource {
pub n: usize,
}

impl Source for FileSource {
fn read(&mut self) -> usize {
self.n
}
}

pub struct BufSource<T> {
pub inner: T,
}

impl<T> Source for BufSource<T> {
fn read(&mut self) -> usize {
0
}
}

pub struct Parents<'a> {
pub current: &'a u32,
}

impl<'a> Iterator for Parents<'a> {
type Item = u32;

fn next(&mut self) -> Option<u32> {
None
}
}

pub struct Wrapper {
pub n: usize,
}

impl Source for &Wrapper {
fn read(&mut self) -> usize {
1
}
}

pub mod nested {
pub struct Scoped {
pub n: usize,
}
}

impl Source for nested::Scoped {
fn read(&mut self) -> usize {
2
}
}

pub struct Own {
pub n: usize,
}

impl From<u32> for Own {
fn from(n: u32) -> Self {
Own { n: n as usize }
}
}

pub trait Base {
fn id(&self) -> u32;
}

impl Base for (u32, u32) {
fn id(&self) -> u32 {
0
}
}

impl Base for dyn Base {
fn id(&self) -> u32 {
1
}
}

impl Base for *const u8 {
fn id(&self) -> u32 {
2
}
}

impl Base for u32 {
fn id(&self) -> u32 {
3
}
}
Loading
Loading