self-review 2026-05-16: tier-based decay rates, implement knowledge_promote, ISE label extraction
Three research-grounded improvements: 1. Tier-based temporal decay in el_runtime.c (engram_node_full, engram_node_layered): Working=48h, Episodic=72h, Semantic=336h, Procedural=720h half-lives. Grounded in ACT-R literature — differentiated decay by chunk type. The temporal_decay_rate field existed but was always 0 (global 168h for everything). New nodes now carry the correct half-life for their tier from creation. 2. Implement route_neuron_knowledge_promote in server.el (was a silent stub): Reads existing node, creates promoted-tier copy with supersedes edge, checkpoints. promote_knowledge MCP tool now has real effect. 3. ISE label extraction + offset support in route_neuron_state_events: POST now extracts 'event' field from content JSON as label (heartbeat, wm_promotion, etc.) instead of always writing 'state-event'. GET now accepts ?offset= for pagination to reach recent ISEs.
This commit is contained in:
Vendored
+62
-3
@@ -685,7 +685,62 @@ el_val_t route_neuron_knowledge_evolve(el_val_t method, el_val_t path, el_val_t
|
||||
}
|
||||
|
||||
el_val_t route_neuron_knowledge_promote(el_val_t method, el_val_t path, el_val_t body) {
|
||||
return EL_STR("{\"ok\":true}");
|
||||
el_val_t id = json_get_string(body, EL_STR("id"));
|
||||
if (str_eq(id, EL_STR(""))) {
|
||||
return EL_STR("{\"ok\":true}");
|
||||
}
|
||||
el_val_t node_json = engram_get_node_json(id);
|
||||
if (str_eq(node_json, EL_STR(""))) {
|
||||
return err_json(EL_STR("node not found"));
|
||||
}
|
||||
if (str_eq(node_json, EL_STR("null"))) {
|
||||
return err_json(EL_STR("node not found"));
|
||||
}
|
||||
el_val_t content = json_get_string(node_json, EL_STR("content"));
|
||||
if (str_eq(content, EL_STR(""))) {
|
||||
return err_json(EL_STR("node has no content"));
|
||||
}
|
||||
el_val_t label = json_get_string(node_json, EL_STR("label"));
|
||||
el_val_t tags = json_get_string(node_json, EL_STR("tags"));
|
||||
el_val_t current_tier = json_get_string(node_json, EL_STR("tier"));
|
||||
el_val_t tier_raw = json_get_string(body, EL_STR("tier"));
|
||||
el_val_t new_tier = EL_STR("");
|
||||
if (str_eq(tier_raw, EL_STR("lesson"))) {
|
||||
new_tier = EL_STR("Semantic");
|
||||
}
|
||||
if (str_eq(tier_raw, EL_STR("canonical"))) {
|
||||
new_tier = EL_STR("Procedural");
|
||||
}
|
||||
if (str_eq(tier_raw, EL_STR("note"))) {
|
||||
new_tier = EL_STR("Episodic");
|
||||
}
|
||||
if (str_eq(new_tier, EL_STR(""))) {
|
||||
if (str_eq(current_tier, EL_STR("Working"))) {
|
||||
new_tier = EL_STR("Episodic");
|
||||
}
|
||||
if (str_eq(current_tier, EL_STR("Episodic"))) {
|
||||
new_tier = EL_STR("Semantic");
|
||||
}
|
||||
if (str_eq(current_tier, EL_STR("Semantic"))) {
|
||||
new_tier = EL_STR("Procedural");
|
||||
}
|
||||
if (str_eq(current_tier, EL_STR("Procedural"))) {
|
||||
new_tier = EL_STR("Procedural");
|
||||
}
|
||||
}
|
||||
if (str_eq(new_tier, EL_STR(""))) {
|
||||
new_tier = EL_STR("Semantic");
|
||||
}
|
||||
el_val_t new_id = engram_node_full(content, EL_STR("Knowledge"), label, el_from_float(0.7), el_from_float(0.8), el_from_float(1.0), new_tier, tags);
|
||||
if (!str_eq(new_id, EL_STR(""))) {
|
||||
engram_connect(new_id, id, el_from_float(1.0), EL_STR("supersedes"));
|
||||
}
|
||||
el_val_t dir = env(EL_STR("ENGRAM_DATA_DIR"));
|
||||
if (str_eq(dir, EL_STR(""))) {
|
||||
dir = EL_STR("/tmp/engram");
|
||||
}
|
||||
engram_write_binary_el(el_str_concat(dir, EL_STR("/engram.db")));
|
||||
return el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"ok\":true,\"id\":\""), new_id), EL_STR("\",\"promoted_from\":\"")), id), EL_STR("\",\"tier\":\"")), new_tier), EL_STR("\"}"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -768,13 +823,17 @@ 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; });
|
||||
return engram_scan_nodes_by_type_json(EL_STR("InternalStateEvent"), limit, 0);
|
||||
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; });
|
||||
return engram_scan_nodes_by_type_json(EL_STR("InternalStateEvent"), limit, offset);
|
||||
}
|
||||
el_val_t content = json_get_string(body, EL_STR("content"));
|
||||
if (str_eq(content, EL_STR(""))) {
|
||||
content = body;
|
||||
}
|
||||
el_val_t id = engram_node_full(content, EL_STR("InternalStateEvent"), EL_STR("state-event"), el_from_float(0.3), el_from_float(0.3), el_from_float(1.0), EL_STR("Working"), EL_STR("internal-state"));
|
||||
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 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