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:
2026-05-16 08:40:01 -05:00
parent fde3ef539c
commit d917165aaf
4 changed files with 140 additions and 10 deletions
+16 -2
View File
@@ -6070,7 +6070,20 @@ el_val_t engram_node_full(el_val_t content, el_val_t node_type, el_val_t label,
if (n->salience <= 0.0 || n->salience > 1.0) n->salience = 0.5;
if (n->importance <= 0.0 || n->importance > 1.0) n->importance = 0.5;
if (n->confidence <= 0.0 || n->confidence > 1.0) n->confidence = 1.0;
n->temporal_decay_rate = 0.0; /* 0 = use global default ENGRAM_DECAY_LAMBDA */
/* Tier-based temporal decay (2026-05-16 self-review, grounded in ACT-R literature).
* Working-memory events fade fastest; semantic knowledge persists 2 weeks;
* procedural/canonical knowledge lasts ~30 days before 50% decay.
* Formula: lambda = ENGRAM_DECAY_LAMBDA * ENGRAM_T_HALF_HOURS / target_half_life_h
* Working=48h 2.310, Episodic=72h 1.617, Semantic=336h 0.347, Procedural=720h 0.162 */
if (ti && *ti) {
if (strcmp(ti, "Working") == 0) n->temporal_decay_rate = 2.310;
else if (strcmp(ti, "Episodic") == 0) n->temporal_decay_rate = 1.617;
else if (strcmp(ti, "Semantic") == 0) n->temporal_decay_rate = 0.347;
else if (strcmp(ti, "Procedural") == 0) n->temporal_decay_rate = 0.162;
else n->temporal_decay_rate = 0.0;
} else {
n->temporal_decay_rate = 0.0; /* global default: 168h half-life */
}
n->activation_count = 0;
int64_t now = engram_now_ms();
n->last_activated = now;
@@ -6146,7 +6159,8 @@ el_val_t engram_node_layered(el_val_t content, el_val_t node_type, el_val_t labe
if (n->salience <= 0.0 || n->salience > 1.0) n->salience = 0.5;
if (n->importance <= 0.0 || n->importance > 1.0) n->importance = 0.5;
if (n->confidence <= 0.0 || n->confidence > 1.0) n->confidence = 1.0;
n->temporal_decay_rate = 0.0;
/* engram_node_layered always creates Working-tier nodes — apply 48h decay */
n->temporal_decay_rate = 2.310;
n->activation_count = 0;
int64_t now = engram_now_ms();
n->last_activated = now;