Skip to content

Commit c5ad6e8

Browse files
DeusDatatest
authored andcommitted
Add cross-repo intelligence mode with CROSS_* edge types
New index_repository mode="cross-repo-intelligence" that matches Routes, Channels, and async topics across indexed projects: - CROSS_HTTP_CALLS: matches HTTP_CALLS edges against Route nodes in other projects via deterministic QN (__route__METHOD__/path) - CROSS_ASYNC_CALLS: matches ASYNC_CALLS edges by broker + topic - CROSS_CHANNEL: matches Channel nodes (EMITS/LISTENS_ON) by name + transport across projects Edges are written bidirectionally: both source and target project DBs get a CROSS_* edge so the link is visible from either side. Usage: index_repository(repo_path="/path", mode="cross-repo-intelligence", target_projects=["*"]) New files: src/pipeline/pass_cross_repo.c/.h Modified: src/mcp/mcp.c (handler + tool schema), Makefile.cbm
1 parent d5c493c commit c5ad6e8

4 files changed

Lines changed: 700 additions & 7 deletions

File tree

Makefile.cbm

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,8 @@ PIPELINE_SRCS = \
189189
src/pipeline/pass_infrascan.c \
190190
src/pipeline/pass_k8s.c \
191191
src/pipeline/pass_similarity.c \
192-
src/pipeline/pass_semantic_edges.c
192+
src/pipeline/pass_semantic_edges.c \
193+
src/pipeline/pass_cross_repo.c
193194

194195
# SimHash / MinHash module
195196
SIMHASH_SRCS = src/simhash/minhash.c

src/mcp/mcp.c

Lines changed: 78 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ enum {
4343
#include <sqlite3.h>
4444
#include "cypher/cypher.h"
4545
#include "pipeline/pipeline.h"
46+
#include "pipeline/pass_cross_repo.h"
4647
#include "cli/cli.h"
4748
#include "watcher/watcher.h"
4849
#include "foundation/mem.h"
@@ -257,13 +258,21 @@ typedef struct {
257258
} tool_def_t;
258259

259260
static const tool_def_t TOOLS[] = {
260-
{"index_repository", "Index a repository into the knowledge graph",
261+
{"index_repository",
262+
"Index a repository into the knowledge graph. "
263+
"Special mode 'cross-repo-intelligence': skip extraction, only match Routes/Channels "
264+
"across projects to create CROSS_HTTP_CALLS/CROSS_ASYNC_CALLS/CROSS_CHANNEL edges. "
265+
"Requires target_projects param. Ensure target projects have fresh indexes first.",
261266
"{\"type\":\"object\",\"properties\":{\"repo_path\":{\"type\":\"string\",\"description\":"
262-
"\"Path to the "
263-
"repository\"},\"mode\":{\"type\":\"string\",\"enum\":[\"full\",\"moderate\",\"fast\"],"
264-
"\"default\":\"full\",\"description\":\"full: all passes including semantic edges. "
265-
"moderate: fast discovery + SIMILAR_TO + SEMANTICALLY_RELATED. fast: structure only."
266-
"\"}},\"required\":[\"repo_path\"]}"},
267+
"\"Path to the repository\"},"
268+
"\"mode\":{\"type\":\"string\","
269+
"\"enum\":[\"full\",\"moderate\",\"fast\",\"cross-repo-intelligence\"],"
270+
"\"default\":\"full\",\"description\":\"full: all passes. moderate: fast + semantic. "
271+
"fast: structure only. cross-repo-intelligence: match Routes/Channels across projects.\"},"
272+
"\"target_projects\":{\"type\":\"array\",\"items\":{\"type\":\"string\"},"
273+
"\"description\":\"Projects to search for cross-repo links (cross-repo-intelligence mode). "
274+
"Use [\\\"*\\\"] for all indexed projects. Run list_projects to see available projects.\"}"
275+
"},\"required\":[\"repo_path\"]}"},
267276

268277
{"search_graph",
269278
"Search the code knowledge graph for functions, classes, routes, and variables. Use INSTEAD "
@@ -2042,6 +2051,62 @@ static char *get_project_root(cbm_mcp_server_t *srv, const char *project) {
20422051

20432052
/* ── index_repository ─────────────────────────────────────────── */
20442053

2054+
/* Handle mode="cross-repo-intelligence" — extract to reduce complexity. */
2055+
static char *handle_cross_repo_mode(const char *repo_path, const char *args) {
2056+
char *project = heap_strdup(cbm_project_name_from_path(repo_path));
2057+
if (!project) {
2058+
return cbm_mcp_text_result("cannot derive project name", true);
2059+
}
2060+
2061+
yyjson_doc *jdoc = yyjson_read(args, strlen(args), 0);
2062+
yyjson_val *jroot = jdoc ? yyjson_doc_get_root(jdoc) : NULL;
2063+
yyjson_val *tp_arr = jroot ? yyjson_obj_get(jroot, "target_projects") : NULL;
2064+
2065+
if (!tp_arr || !yyjson_is_arr(tp_arr) || yyjson_arr_size(tp_arr) == 0) {
2066+
yyjson_doc_free(jdoc);
2067+
free(project);
2068+
return cbm_mcp_text_result(
2069+
"{\"error\":\"target_projects is required for cross-repo-intelligence mode. "
2070+
"Use [\\\"*\\\"] for all projects. Run list_projects to see available.\"}",
2071+
true);
2072+
}
2073+
2074+
int tp_count = (int)yyjson_arr_size(tp_arr);
2075+
const char **targets = malloc((size_t)tp_count * sizeof(char *));
2076+
size_t idx;
2077+
size_t max;
2078+
yyjson_val *val;
2079+
int ti = 0;
2080+
yyjson_arr_foreach(tp_arr, idx, max, val) {
2081+
targets[ti++] = yyjson_get_str(val);
2082+
}
2083+
2084+
cbm_cross_repo_result_t result = cbm_cross_repo_match(project, targets, tp_count);
2085+
free(targets);
2086+
yyjson_doc_free(jdoc);
2087+
2088+
int total = result.http_edges + result.async_edges + result.channel_edges;
2089+
yyjson_mut_doc *doc = yyjson_mut_doc_new(NULL);
2090+
yyjson_mut_val *root = yyjson_mut_obj(doc);
2091+
yyjson_mut_doc_set_root(doc, root);
2092+
yyjson_mut_obj_add_str(doc, root, "status", "success");
2093+
yyjson_mut_obj_add_str(doc, root, "mode", "cross-repo-intelligence");
2094+
yyjson_mut_obj_add_strcpy(doc, root, "project", project);
2095+
yyjson_mut_obj_add_int(doc, root, "projects_scanned", result.projects_scanned);
2096+
yyjson_mut_obj_add_int(doc, root, "cross_http_calls", result.http_edges);
2097+
yyjson_mut_obj_add_int(doc, root, "cross_async_calls", result.async_edges);
2098+
yyjson_mut_obj_add_int(doc, root, "cross_channel", result.channel_edges);
2099+
yyjson_mut_obj_add_int(doc, root, "total_cross_edges", total);
2100+
yyjson_mut_obj_add_real(doc, root, "elapsed_ms", result.elapsed_ms);
2101+
2102+
char *json = yy_doc_to_str(doc);
2103+
yyjson_mut_doc_free(doc);
2104+
free(project);
2105+
char *out = cbm_mcp_text_result(json, false);
2106+
free(json);
2107+
return out;
2108+
}
2109+
20452110
static char *handle_index_repository(cbm_mcp_server_t *srv, const char *args) {
20462111
char *repo_path = cbm_mcp_get_string_arg(args, "repo_path");
20472112
char *mode_str = cbm_mcp_get_string_arg(args, "mode");
@@ -2052,6 +2117,13 @@ static char *handle_index_repository(cbm_mcp_server_t *srv, const char *args) {
20522117
return cbm_mcp_text_result("repo_path is required", true);
20532118
}
20542119

2120+
if (mode_str && strcmp(mode_str, "cross-repo-intelligence") == 0) {
2121+
free(mode_str);
2122+
char *result = handle_cross_repo_mode(repo_path, args);
2123+
free(repo_path);
2124+
return result;
2125+
}
2126+
20552127
cbm_index_mode_t mode = CBM_MODE_FULL;
20562128
if (mode_str && strcmp(mode_str, "fast") == 0) {
20572129
mode = CBM_MODE_FAST;

0 commit comments

Comments
 (0)