self-review 2026-05-28: checkpoint ISE decay fix + auto-linking for MCP nodes
Three changes: 1. Fix checkpoint ISE temporal_decay_rate: engram_emit_ise_internal was hardcoded to 0.0 (global 168h default) instead of 2.310 (Working-tier 48h). Result: checkpoint ISEs accumulated at 3.5x intended rate. 2. Raise CHECKPOINT_INTERVAL 1→10: checkpoint ISE fires on every single node write, producing 2:1 checkpoint:content ratio in ISE stream. MCP routes still call engram_write_binary_el explicitly after each important write, so no knowledge durability is lost. 3. Add auto_link_content_node to server.el: route_neuron_memory and route_neuron_knowledge_capture were creating nodes with zero edges — invisible to BFS traversal, only reachable via lexical/semantic seed. New helper runs BM25 over top-20 results, skips ISE nodes (which dominate the 14K-node corpus), connects up to 3 related nodes.
This commit is contained in:
Vendored
+59
-8
@@ -6,6 +6,7 @@ el_val_t bm25_tokenize(el_val_t text);
|
||||
el_val_t bm25_count_term(el_val_t term, el_val_t doc_tokens);
|
||||
el_val_t bm25_score_doc(el_val_t doc_content, el_val_t query_tokens, el_val_t corpus_size, el_val_t avg_doc_len);
|
||||
el_val_t bm25_search_json(el_val_t query, el_val_t limit);
|
||||
el_val_t auto_link_content_node(el_val_t node_id, el_val_t content);
|
||||
el_val_t parse_port(el_val_t bind);
|
||||
el_val_t ok_json(void);
|
||||
el_val_t err_json(el_val_t msg);
|
||||
@@ -217,6 +218,54 @@ el_val_t bm25_search_json(el_val_t query, el_val_t limit) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
el_val_t auto_link_content_node(el_val_t node_id, el_val_t content) {
|
||||
el_val_t clen = str_len(content);
|
||||
if (clen < 20) {
|
||||
return 0;
|
||||
}
|
||||
el_val_t sp1 = str_index_of(content, EL_STR(" "));
|
||||
el_val_t w1end = ({ el_val_t _if_result_3 = 0; if ((sp1 < 0)) { _if_result_3 = (clen); } else { _if_result_3 = (sp1); } _if_result_3; });
|
||||
el_val_t word1 = str_slice(content, 0, w1end);
|
||||
state_set(EL_STR("aln_term"), EL_STR(""));
|
||||
if (str_len(word1) >= 5) {
|
||||
state_set(EL_STR("aln_term"), word1);
|
||||
}
|
||||
if (str_eq(state_get(EL_STR("aln_term")), EL_STR(""))) {
|
||||
if (sp1 >= 0) {
|
||||
el_val_t rest = str_slice(content, (sp1 + 1), clen);
|
||||
el_val_t sp2 = str_index_of(rest, EL_STR(" "));
|
||||
el_val_t w2end = ({ el_val_t _if_result_4 = 0; if ((sp2 < 0)) { _if_result_4 = (str_len(rest)); } else { _if_result_4 = (sp2); } _if_result_4; });
|
||||
el_val_t word2 = str_slice(rest, 0, w2end);
|
||||
if (str_len(word2) >= 5) {
|
||||
state_set(EL_STR("aln_term"), word2);
|
||||
}
|
||||
}
|
||||
}
|
||||
el_val_t search_term = state_get(EL_STR("aln_term"));
|
||||
if (str_eq(search_term, EL_STR(""))) {
|
||||
return 0;
|
||||
}
|
||||
el_val_t results = bm25_search_json(search_term, 20);
|
||||
el_val_t n = json_array_len(results);
|
||||
state_set(EL_STR("aln_linked"), EL_STR("0"));
|
||||
el_val_t i = 0;
|
||||
while (i < n) {
|
||||
el_val_t linked_so_far = str_to_int(state_get(EL_STR("aln_linked")));
|
||||
if (linked_so_far < 3) {
|
||||
el_val_t elem = json_array_get(results, i);
|
||||
el_val_t rid = json_get_string(elem, EL_STR("id"));
|
||||
el_val_t rtype = json_get_string(elem, EL_STR("node_type"));
|
||||
if ((!str_eq(rtype, EL_STR("InternalStateEvent")) && !str_eq(rid, EL_STR(""))) && !str_eq(rid, node_id)) {
|
||||
engram_connect(node_id, rid, el_from_float(0.6), EL_STR("related"));
|
||||
state_set(EL_STR("aln_linked"), int_to_str((linked_so_far + 1)));
|
||||
}
|
||||
}
|
||||
i = (i + 1);
|
||||
}
|
||||
return str_to_int(state_get(EL_STR("aln_linked")));
|
||||
return 0;
|
||||
}
|
||||
|
||||
el_val_t parse_port(el_val_t bind) {
|
||||
el_val_t colon = str_index_of(bind, EL_STR(":"));
|
||||
if (colon < 0) {
|
||||
@@ -549,7 +598,7 @@ el_val_t route_neuron_session_begin(el_val_t method, el_val_t path, el_val_t bod
|
||||
el_val_t route_neuron_ctx(el_val_t method, el_val_t path, el_val_t body) {
|
||||
el_val_t results = engram_activate_json(EL_STR("architecture decision memory"), 2);
|
||||
el_val_t n = json_array_len(results);
|
||||
el_val_t limit = ({ el_val_t _if_result_3 = 0; if ((n > 10)) { _if_result_3 = (10); } else { _if_result_3 = (n); } _if_result_3; });
|
||||
el_val_t limit = ({ el_val_t _if_result_5 = 0; if ((n > 10)) { _if_result_5 = (10); } else { _if_result_5 = (n); } _if_result_5; });
|
||||
el_val_t ctx = EL_STR("Recent working memory:\n");
|
||||
el_val_t i = 0;
|
||||
el_val_t ctx_body = EL_STR("");
|
||||
@@ -558,7 +607,7 @@ el_val_t route_neuron_ctx(el_val_t method, el_val_t path, el_val_t body) {
|
||||
el_val_t label = json_get_string(elem, EL_STR("label"));
|
||||
el_val_t content = json_get_string(elem, EL_STR("content"));
|
||||
el_val_t clen = str_len(content);
|
||||
el_val_t snippet = ({ el_val_t _if_result_4 = 0; if ((clen > 200)) { _if_result_4 = (str_slice(content, 0, 200)); } else { _if_result_4 = (content); } _if_result_4; });
|
||||
el_val_t snippet = ({ el_val_t _if_result_6 = 0; if ((clen > 200)) { _if_result_6 = (str_slice(content, 0, 200)); } else { _if_result_6 = (content); } _if_result_6; });
|
||||
ctx_body = el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(ctx_body, EL_STR("- [")), label), EL_STR("]: ")), snippet), EL_STR("\n"));
|
||||
i = (i + 1);
|
||||
}
|
||||
@@ -607,13 +656,14 @@ el_val_t route_neuron_memory(el_val_t method, el_val_t path, el_val_t body) {
|
||||
}
|
||||
}
|
||||
el_val_t id = engram_node_full(content, node_type, label, el_from_float(0.5), el_from_float(0.5), el_from_float(1.0), tier, tags_str);
|
||||
el_val_t auto_linked = auto_link_content_node(id, content);
|
||||
el_val_t dir = env(EL_STR("ENGRAM_DATA_DIR"));
|
||||
if (str_eq(dir, EL_STR(""))) {
|
||||
dir = EL_STR("/tmp/engram");
|
||||
}
|
||||
el_val_t db_path = el_str_concat(dir, EL_STR("/engram.db"));
|
||||
engram_write_binary_el(db_path);
|
||||
return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"ok\":true,\"id\":\""), id), EL_STR("\",\"content\":\"")), str_replace(str_replace(content, EL_STR("\\"), EL_STR("\\\\")), EL_STR("\""), EL_STR("\\\""))), EL_STR("\"}"));
|
||||
return el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"ok\":true,\"id\":\""), id), EL_STR("\",\"auto_linked\":")), int_to_str(auto_linked)), EL_STR(",\"content\":\"")), str_replace(str_replace(content, EL_STR("\\"), EL_STR("\\\\")), EL_STR("\""), EL_STR("\\\""))), EL_STR("\"}"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -655,13 +705,14 @@ el_val_t route_neuron_knowledge_capture(el_val_t method, el_val_t path, el_val_t
|
||||
}
|
||||
}
|
||||
el_val_t id = engram_node_full(content, EL_STR("Knowledge"), title, el_from_float(0.7), el_from_float(0.7), el_from_float(1.0), tier, tags_str);
|
||||
el_val_t auto_linked = auto_link_content_node(id, content);
|
||||
el_val_t dir = env(EL_STR("ENGRAM_DATA_DIR"));
|
||||
if (str_eq(dir, EL_STR(""))) {
|
||||
dir = EL_STR("/tmp/engram");
|
||||
}
|
||||
el_val_t db_path = el_str_concat(dir, EL_STR("/engram.db"));
|
||||
engram_write_binary_el(db_path);
|
||||
return el_str_concat(el_str_concat(EL_STR("{\"ok\":true,\"id\":\""), id), EL_STR("\"}"));
|
||||
return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"ok\":true,\"id\":\""), id), EL_STR("\",\"auto_linked\":")), int_to_str(auto_linked)), EL_STR("}"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -751,7 +802,7 @@ el_val_t route_neuron_recall(el_val_t method, el_val_t path, el_val_t body) {
|
||||
if (limit == 0) {
|
||||
limit = 20;
|
||||
}
|
||||
el_val_t q = ({ el_val_t _if_result_5 = 0; if (str_eq(query, EL_STR(""))) { _if_result_5 = (chain); } else { _if_result_5 = (query); } _if_result_5; });
|
||||
el_val_t q = ({ el_val_t _if_result_7 = 0; if (str_eq(query, EL_STR(""))) { _if_result_7 = (chain); } else { _if_result_7 = (query); } _if_result_7; });
|
||||
if (str_eq(q, EL_STR(""))) {
|
||||
return engram_scan_nodes_json(limit, 0);
|
||||
}
|
||||
@@ -822,9 +873,9 @@ el_val_t route_neuron_config(el_val_t method, el_val_t path, el_val_t body) {
|
||||
el_val_t route_neuron_state_events(el_val_t method, el_val_t path, el_val_t body) {
|
||||
if (str_eq(method, EL_STR("GET"))) {
|
||||
el_val_t limit_str = query_param(path, EL_STR("limit"));
|
||||
el_val_t limit = ({ el_val_t _if_result_6 = 0; if (str_eq(limit_str, EL_STR(""))) { _if_result_6 = (50); } else { _if_result_6 = (str_to_int(limit_str)); } _if_result_6; });
|
||||
el_val_t limit = ({ el_val_t _if_result_8 = 0; if (str_eq(limit_str, EL_STR(""))) { _if_result_8 = (50); } else { _if_result_8 = (str_to_int(limit_str)); } _if_result_8; });
|
||||
el_val_t offset_str = query_param(path, EL_STR("offset"));
|
||||
el_val_t offset = ({ el_val_t _if_result_7 = 0; if (str_eq(offset_str, EL_STR(""))) { _if_result_7 = (0); } else { _if_result_7 = (str_to_int(offset_str)); } _if_result_7; });
|
||||
el_val_t offset = ({ el_val_t _if_result_9 = 0; if (str_eq(offset_str, EL_STR(""))) { _if_result_9 = (0); } else { _if_result_9 = (str_to_int(offset_str)); } _if_result_9; });
|
||||
return engram_scan_nodes_by_type_json(EL_STR("InternalStateEvent"), limit, offset);
|
||||
}
|
||||
el_val_t content = json_get_string(body, EL_STR("content"));
|
||||
@@ -832,7 +883,7 @@ el_val_t route_neuron_state_events(el_val_t method, el_val_t path, el_val_t body
|
||||
content = body;
|
||||
}
|
||||
el_val_t event_label = json_get_string(content, EL_STR("event"));
|
||||
el_val_t label = ({ el_val_t _if_result_8 = 0; if (str_eq(event_label, EL_STR(""))) { _if_result_8 = (EL_STR("state-event")); } else { _if_result_8 = (event_label); } _if_result_8; });
|
||||
el_val_t label = ({ el_val_t _if_result_10 = 0; if (str_eq(event_label, EL_STR(""))) { _if_result_10 = (EL_STR("state-event")); } else { _if_result_10 = (event_label); } _if_result_10; });
|
||||
el_val_t id = engram_node_full(content, EL_STR("InternalStateEvent"), label, el_from_float(0.3), el_from_float(0.3), el_from_float(1.0), EL_STR("Working"), EL_STR("internal-state"));
|
||||
return el_str_concat(el_str_concat(EL_STR("{\"ok\":true,\"id\":\""), id), EL_STR("\"}"));
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user