mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-10-29 07:13:44 +08:00
feat(mcp): report index publish metadata
Expose index_repository publish_kind and graph_changed in the JSON result so MCP clients can tell whether a run used a full, no-op, exact incremental, or containment route without relying on stderr logs. Add a reusable pipeline publish-kind string helper plus focused pipeline and incremental response-contract tests. This is additive response metadata only; it does not change indexing behavior or enable incremental by default. Signed-off-by: Andrew Hundt <ATHundt@gmail.com>
This commit is contained in:
@@ -4995,6 +4995,9 @@ static char *handle_index_repository(cbm_mcp_server_t *srv, const char *args) {
|
||||
|
||||
yyjson_mut_obj_add_str(doc, root, "project", project_name);
|
||||
yyjson_mut_obj_add_str(doc, root, "status", rc == 0 ? "indexed" : "error");
|
||||
yyjson_mut_obj_add_str(doc, root, "publish_kind",
|
||||
cbm_pipeline_publish_kind_name(publish_kind));
|
||||
yyjson_mut_obj_add_bool(doc, root, "graph_changed", graph_changed);
|
||||
|
||||
if (rc == 0) {
|
||||
cbm_store_t *store = resolve_store(srv, project_name);
|
||||
|
||||
@@ -403,6 +403,23 @@ cbm_pipeline_publish_kind_t cbm_pipeline_publish_kind(const cbm_pipeline_t *p) {
|
||||
return p ? p->publish_kind : CBM_PIPELINE_PUBLISH_NONE;
|
||||
}
|
||||
|
||||
const char *cbm_pipeline_publish_kind_name(cbm_pipeline_publish_kind_t kind) {
|
||||
switch (kind) {
|
||||
case CBM_PIPELINE_PUBLISH_NONE:
|
||||
return "none";
|
||||
case CBM_PIPELINE_PUBLISH_FULL:
|
||||
return "full";
|
||||
case CBM_PIPELINE_PUBLISH_INCREMENTAL_NOOP:
|
||||
return "incremental_noop";
|
||||
case CBM_PIPELINE_PUBLISH_INCREMENTAL_EXACT:
|
||||
return "incremental_exact";
|
||||
case CBM_PIPELINE_PUBLISH_INCREMENTAL_CONTAINMENT:
|
||||
return "incremental_containment";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
void cbm_pipeline_set_graph_changed(cbm_pipeline_t *p, bool changed) {
|
||||
if (p) {
|
||||
p->graph_changed = changed;
|
||||
|
||||
@@ -141,6 +141,7 @@ bool cbm_pipeline_graph_changed(const cbm_pipeline_t *p);
|
||||
/* Last publish route for the most recent run. This is observability for callers
|
||||
* that need derived-view policy decisions; it does not change graph contents. */
|
||||
cbm_pipeline_publish_kind_t cbm_pipeline_publish_kind(const cbm_pipeline_t *p);
|
||||
const char *cbm_pipeline_publish_kind_name(cbm_pipeline_publish_kind_t kind);
|
||||
|
||||
/* ── Index lock (prevents concurrent pipeline runs on same DB) ──── */
|
||||
|
||||
|
||||
@@ -2174,6 +2174,21 @@ TEST(tool_index_mode_fast) {
|
||||
PASS();
|
||||
}
|
||||
|
||||
TEST(tool_index_publish_metadata) {
|
||||
double ms;
|
||||
char *r = call_tool_timed("index_repository", &ms, "{\"repo_path\":\"%s\",\"mode\":\"fast\"}",
|
||||
g_repodir);
|
||||
ASSERT(r != NULL);
|
||||
ASSERT(strstr(r, "\\\"publish_kind\\\":\\\"") != NULL);
|
||||
ASSERT(strstr(r, "\\\"graph_changed\\\":") != NULL);
|
||||
ASSERT(strstr(r, "\\\"publish_kind\\\":\\\"full\\\"") != NULL ||
|
||||
strstr(r, "\\\"publish_kind\\\":\\\"incremental_noop\\\"") != NULL ||
|
||||
strstr(r, "\\\"publish_kind\\\":\\\"incremental_exact\\\"") != NULL ||
|
||||
strstr(r, "\\\"publish_kind\\\":\\\"incremental_containment\\\"") != NULL);
|
||||
free(r);
|
||||
PASS();
|
||||
}
|
||||
|
||||
TEST(tool_index_invalid_path) {
|
||||
double ms;
|
||||
char *r = call_tool_timed("index_repository", &ms, "{\"repo_path\":\"/nonexistent/path/xyz\"}");
|
||||
@@ -3264,6 +3279,7 @@ SUITE(incremental) {
|
||||
|
||||
/* Phase 19: index_repository params */
|
||||
RUN_TEST(tool_index_mode_fast);
|
||||
RUN_TEST(tool_index_publish_metadata);
|
||||
RUN_TEST(tool_index_invalid_path);
|
||||
RUN_TEST(tool_index_missing_param);
|
||||
|
||||
|
||||
@@ -10013,6 +10013,19 @@ TEST(pipeline_unit_threshold_setters_clamp_invalid_values) {
|
||||
PASS();
|
||||
}
|
||||
|
||||
TEST(pipeline_publish_kind_names_are_stable) {
|
||||
ASSERT_STR_EQ(cbm_pipeline_publish_kind_name(CBM_PIPELINE_PUBLISH_NONE), "none");
|
||||
ASSERT_STR_EQ(cbm_pipeline_publish_kind_name(CBM_PIPELINE_PUBLISH_FULL), "full");
|
||||
ASSERT_STR_EQ(cbm_pipeline_publish_kind_name(CBM_PIPELINE_PUBLISH_INCREMENTAL_NOOP),
|
||||
"incremental_noop");
|
||||
ASSERT_STR_EQ(cbm_pipeline_publish_kind_name(CBM_PIPELINE_PUBLISH_INCREMENTAL_EXACT),
|
||||
"incremental_exact");
|
||||
ASSERT_STR_EQ(cbm_pipeline_publish_kind_name(CBM_PIPELINE_PUBLISH_INCREMENTAL_CONTAINMENT),
|
||||
"incremental_containment");
|
||||
ASSERT_STR_EQ(cbm_pipeline_publish_kind_name((cbm_pipeline_publish_kind_t)999), "unknown");
|
||||
PASS();
|
||||
}
|
||||
|
||||
TEST(pipeline_apply_config_sets_all_thresholds) {
|
||||
char tmpdir[256];
|
||||
snprintf(tmpdir, sizeof(tmpdir), "/tmp/cbm_pipeline_cfg_XXXXXX");
|
||||
@@ -11175,6 +11188,7 @@ SUITE(pipeline) {
|
||||
/* Resource management & internal helper tests */
|
||||
RUN_TEST(pipeline_empty_path);
|
||||
RUN_TEST(pipeline_project_name_content);
|
||||
RUN_TEST(pipeline_publish_kind_names_are_stable);
|
||||
RUN_TEST(pipeline_cancel_sets_flag);
|
||||
RUN_TEST(pipeline_double_cancel);
|
||||
RUN_TEST(pipeline_double_free_prevention);
|
||||
|
||||
Reference in New Issue
Block a user