Skip to content
Closed
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
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ Removes all agent configs, skills, hooks, and instructions. Does not remove the
- **Louvain community detection**: Discovers functional modules by clustering call edges
- **Git diff impact mapping**: `detect_changes` maps uncommitted changes to affected symbols with risk classification
- **Call graph**: Resolves function calls across files and packages (import-aware, type-inferred)
- **Angular metadata**: Preserves literal `Component`, `Directive`, `Pipe`, `Injectable`, and
`NgModule` roles on existing class nodes, including selectors, standalone status, external
templates/styles, and resolvable standalone imports
- **Dead code detection**: Finds functions with zero callers, excluding entry points
- **Cypher-like queries**: `MATCH (f:Function)-[:CALLS]->(g) WHERE f.name = 'main' RETURN g.name`

Expand Down Expand Up @@ -445,6 +448,10 @@ codebase-memory-mcp cli --raw search_graph '{"project": "my-project", "label": "

`Project`, `Package`, `Folder`, `File`, `Module`, `Class`, `Function`, `Method`, `Interface`, `Enum`, `Type`, `Route`, `Resource`

Angular declarations remain `Class` nodes. Their queryable properties include `angular_kind`,
`selector`, `standalone`, `templateUrl`, `styleUrls`, and `angular_imports`; resolved standalone
dependencies use `IMPORTS` edges with `via: "angular_metadata"`.

### Edge Types

`CONTAINS_PACKAGE`, `CONTAINS_FOLDER`, `CONTAINS_FILE`, `DEFINES`, `DEFINES_METHOD`, `IMPORTS`, `CALLS`, `HTTP_CALLS`, `ASYNC_CALLS`, `IMPLEMENTS`, `HANDLES`, `USAGE`, `CONFIGURES`, `WRITES`, `MEMBER_OF`, `TESTS`, `USES_TYPE`, `FILE_CHANGES_WITH`
Expand Down
5 changes: 3 additions & 2 deletions internal/cbm/cbm.c
Original file line number Diff line number Diff line change
Expand Up @@ -979,11 +979,12 @@ static CBMFileResult *cbm_extract_file_impl(const char *source, int source_len,
.root = root,
};

// Run extractors: defs + imports use separate walks (unique recursion patterns),
// Run extractors: imports + defs use separate walks (unique recursion patterns),
// then a single unified cursor walk handles the remaining 7 extractors.
cbm_extract_definitions(&ctx);
cbm_extract_imports(&ctx);
cbm_extract_definitions(&ctx);
cbm_extract_unified(&ctx);
cbm_propagate_angular_http_wrappers(&ctx);

// Channel detection (Socket.IO / EventEmitter) — JS/TS only.
cbm_extract_channels(&ctx);
Expand Down
40 changes: 26 additions & 14 deletions internal/cbm/cbm.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,20 +195,30 @@ typedef struct {
const char **return_types; // NULL-terminated array (NULL if none)
const char *route_path; // HTTP route path from decorator (e.g., "/api/users") or NULL
const char *route_method; // HTTP method from decorator (e.g., "POST") or NULL
int complexity; // cyclomatic complexity
int cognitive; // cognitive complexity (nesting-weighted)
int loop_count; // number of loop constructs in the body
int loop_depth; // max nested-loop depth (bottleneck proxy)
bool is_recursive; // body contains a direct self-call (seed for "recursive")
int param_count; // number of parameters (large = complexity smell)
int max_access_depth; // deepest chained member/subscript access (a.b.c.d)
int linear_scan_in_loop; // count of linear-scan calls (find/contains/indexOf) inside loops
int alloc_in_loop; // count of allocation/append calls inside loops
bool recursion_in_loop; // a self-call occurs inside a loop body
bool unguarded_recursion; // recursive with no self-call guarded by a conditional
int lines; // body line count
uint32_t *fingerprint; // MinHash fingerprint (arena-allocated, K values) or NULL
int fingerprint_k; // number of hash values (CBM_MINHASH_K or 0)

const char *route_framework; // Producer framework with routing semantics (e.g., "aspnet")
const char *angular_kind; // component/directive/pipe/injectable/ng_module or NULL
const char *angular_selector; // literal Component/Directive selector or NULL
const char *angular_template_url; // literal external template path or NULL
const char **angular_style_urls; // NULL-terminated literal stylesheet paths
const char **angular_imports; // NULL-terminated standalone dependency identifiers
bool angular_standalone; // literal standalone value when explicitly configured
bool angular_standalone_set; // distinguishes explicit false from an absent property

int complexity; // cyclomatic complexity
int cognitive; // cognitive complexity (nesting-weighted)
int loop_count; // number of loop constructs in the body
int loop_depth; // max nested-loop depth (bottleneck proxy)
bool is_recursive; // body contains a direct self-call (seed for "recursive")
int param_count; // number of parameters (large = complexity smell)
int max_access_depth; // deepest chained member/subscript access (a.b.c.d)
int linear_scan_in_loop; // count of linear-scan calls (find/contains/indexOf) inside loops
int alloc_in_loop; // count of allocation/append calls inside loops
bool recursion_in_loop; // a self-call occurs inside a loop body
bool unguarded_recursion; // recursive with no self-call guarded by a conditional
int lines; // body line count
uint32_t *fingerprint; // MinHash fingerprint (arena-allocated, K values) or NULL
int fingerprint_k; // number of hash values (CBM_MINHASH_K or 0)
bool is_exported;
bool is_abstract;
bool is_test;
Expand All @@ -231,6 +241,7 @@ typedef struct {
const char *callee_name; // raw callee text ("pkg.Func", "foo")
const char *enclosing_func_qn; // QN of enclosing function (or module QN)
const char *first_string_arg; // first string literal argument (URL, topic, key) or NULL
const char *asset_path; // normalized frontend asset path or NULL
const char *second_arg_name; // second argument identifier (handler ref) or NULL
CBMCallArg args[CBM_MAX_CALL_ARGS]; // first N arguments with expressions
int arg_count; // number of captured arguments
Expand Down Expand Up @@ -630,6 +641,7 @@ void cbm_extract_channels(CBMExtractCtx *ctx);

// Single-pass unified extraction (replaces the 7 calls above except defs+imports).
void cbm_extract_unified(CBMExtractCtx *ctx);
void cbm_propagate_angular_http_wrappers(CBMExtractCtx *ctx);

// K8s / Kustomize semantic extractor (called when language is CBM_LANG_K8S or CBM_LANG_KUSTOMIZE).
void cbm_extract_k8s(CBMExtractCtx *ctx);
Expand Down
Loading
Loading