M-INTEROCEPTION P1: two-threshold consolidation layer (ENGRAM_CONSOLIDATION, default OFF)

The co-activation accrual already works (hebb is an EWMA over co-firing); what
was missing is the promotion layer from design §9 that turns accrual into
durable structure. This adds it on top, entirely behind ENGRAM_CONSOLIDATION so
the OFF path is byte-identical to trunk.

CONNECTION threshold ("connection IS consolidation"): when a strongly-firing
InternalStateEvent is created (salience >= ENGRAM_CONSOL_CONN_MIN, default 0.6),
wire hebbian-associate edges from it to the top-K working-memory nodes active at
that instant (ENGRAM_CONSOL_WM_TOPK, default 5), provenance-tagged
"consolidated-from-ISE" and dedup-guarded. A sub-threshold ISE forms nothing (a
shower thought) and drifts out at the existing 48h prune.

PERMANENCE threshold (rare): engram_consolidate_permanence(node) marks a node
whose rehearsed ACT-R base-level clears ENGRAM_CONSOL_PERM_MIN durable via a
reversible metadata marker; engram_prune_telemetry then exempts it (gated, so no
trunk node is ever affected). Idempotent, no double-promote.

Thresholds are env-tunable for A/B without a rebuild.

MEASURED on a copy (throwaway HOME):
- Headline accrual curve (flag OFF, pure trunk) over N co-activations of a wired
  pair — hebb_max: N=1 -> 1e-4 (=ETA), N=100 -> 0.010, N=1625 -> 0.150
  (LINK_MIN, where an unwired pair consolidates), N=3000 -> 0.259; tracks the
  analytic EWMA 1-0.9999^N within measurement noise (co-activation P~1).
- Strong ISE wired 2 edges to exactly the wm_top nodes (hebb-a, hebb-b); weak
  ISE formed 0; edges carry the reversible provenance marker.
- Promoted node survived the 48h prune (2->1 nodes); ephemeral ISE swept.
- Flag OFF: ISE creation added 0 edges, permanence returned 0 (no-op).
ASan+UBSan clean.
This commit is contained in:
2026-08-12 23:36:24 -05:00
parent c20cb3b97c
commit 5f6ce5ca1f
5 changed files with 389 additions and 0 deletions
+113
View File
@@ -7914,6 +7914,36 @@ el_val_t engram_text_health_json(void) {
return el_wrap_str(el_strdup(buf));
}
/* ── M-INTEROCEPTION P1: two-threshold consolidation (ENGRAM_CONSOLIDATION,
* default OFF)
* Design §9. "Connection IS consolidation." This is a promotion LAYER on top
* of the already-working co-activation accrual (see ENGRAM_HEBB_* above); it
* does not change how hebb accrues. Two thresholds:
* CONNECTION when a strongly-firing InternalStateEvent is created, wire
* hebbian-associate edges from it to the nodes that were in working memory
* at that moment (its wm_top). Below the bar: no edges a shower thought
* that drifts out at the 48h ISE prune. (eg_consolidate_ise_connect)
* PERMANENCE (rare) a node whose rehearsed ACT-R base-level crosses the
* higher bar is marked durable (metadata provenance "consolidated-from-ISE")
* and is thereafter exempt from engram_prune_telemetry. Reversible: drop the
* marker. Dedup-guarded (eg_edge_exists_between, no double-promote).
* Every branch is inert unless ENGRAM_CONSOLIDATION is set OFF path is
* byte-identical to trunk. Thresholds env-tunable for A/B without a rebuild. */
static int eg_consolidation_on(void){
static int cached=-1;
if(cached<0){ const char* s=getenv("ENGRAM_CONSOLIDATION"); cached=(s&&s[0]&&s[0]!='0')?1:0; }
return cached;
}
static double eg_consol_conn_min(void){ const char* s=getenv("ENGRAM_CONSOL_CONN_MIN"); double v=s?atof(s):0.6; if(!(v>=0.0&&v<=1.0))v=0.6; return v; }
static double eg_consol_perm_min(void){ const char* s=getenv("ENGRAM_CONSOL_PERM_MIN"); return s?atof(s):0.9; }
static int eg_consol_wm_topk(void){ const char* s=getenv("ENGRAM_CONSOL_WM_TOPK"); int v=s?atoi(s):5; if(v<0)v=0; if(v>64)v=64; return v; }
/* Durable marker is carried in node metadata (persisted, reversible) rather than
* a new struct field, so it survives the store round-trip with no schema change. */
static int eg_node_is_durable(const EngramNode* n){
return n && n->metadata && strstr(n->metadata, "consolidated-from-ISE") != NULL;
}
static void eg_consolidate_ise_connect(EngramNode* ise);
el_val_t engram_node_full(el_val_t content, el_val_t node_type, el_val_t label,
el_val_t salience, el_val_t importance, el_val_t confidence,
el_val_t tier, el_val_t tags) {
@@ -7956,6 +7986,8 @@ el_val_t engram_node_full(el_val_t content, el_val_t node_type, el_val_t label,
engram_idmap_put(g, n->id, new_idx_full);
engram_adj_on_node_added(g);
if (engram_store_enabled()) eg_store_put_node(n);
/* P1 CONNECTION threshold: self-gated (inert unless ENGRAM_CONSOLIDATION). */
eg_consolidate_ise_connect(n);
return el_wrap_str(el_strdup(n->id));
}
@@ -8266,6 +8298,10 @@ el_val_t engram_prune_telemetry(el_val_t older_than_ms) {
n->created_at < cutoff &&
!(n->label && strcmp(n->label, "session-start") == 0) &&
!(n->content && strstr(n->content, "self_review"));
/* P1 PERMANENCE: a node promoted past the permanence bar is durable and
* must not be swept by the 48h telemetry prune. Gated so the OFF path is
* byte-identical (no trunk node ever carries the marker). */
if (eg_consolidation_on() && prunable && eg_node_is_durable(n)) prunable = 0;
if (prunable && removed < cap) {
removed_ids[removed++] = n->id; /* keep id for edge sweep */
free(n->content); free(n->node_type); free(n->label);
@@ -8767,6 +8803,83 @@ static int eg_edge_exists_between(EngramStore* g, const char* a, const char* b)
return 0;
}
/* P1 CONNECTION threshold (design §9). When a strongly-firing ISE is created,
* wire hebbian-associate edges from it to the wm_top nodes active at that
* moment. Self-gated: returns immediately unless ENGRAM_CONSOLIDATION is set,
* the node is an InternalStateEvent, and its salience clears the connection bar
* so a sub-threshold ISE forms nothing (a shower thought), which then drifts
* out at the 48h prune. Edges are provenance-tagged "consolidated-from-ISE"
* (reversible: deletable by that marker) and dedup-guarded via
* eg_edge_exists_between. They accrue/decay through the normal hebb machinery
* and are swept with their ISE at the 48h prune unless the ISE is promoted to
* permanence. O(node_count) per qualifying ISE same order as the
* engram_prune_telemetry already run on ISE insert. */
static void eg_consolidate_ise_connect(EngramNode* ise){
if(!eg_consolidation_on()) return;
if(!ise || !ise->node_type || strcmp(ise->node_type,"InternalStateEvent")!=0) return;
if(ise->salience < eg_consol_conn_min()) return; /* below connection bar */
int K = eg_consol_wm_topk();
if(K<=0) return;
if(K>64) K=64;
EngramStore* g = engram_get();
/* Select the top-K working-memory members by weight (excluding ISEs and
* self). Bounded selection, no allocation. */
int64_t best_idx[64]; double best_w[64]; int nb=0;
for(int64_t i=0;i<g->node_count;i++){
EngramNode* t=&g->nodes[i];
if(t==ise) continue;
double w=t->working_memory_weight;
if(w<=0.0) continue;
if(t->node_type && strcmp(t->node_type,"InternalStateEvent")==0) continue;
if(nb<K){ best_idx[nb]=i; best_w[nb]=w; nb++; }
else { int m=0; for(int j=1;j<nb;j++) if(best_w[j]<best_w[m]) m=j;
if(w>best_w[m]){ best_w[m]=w; best_idx[m]=i; } }
}
int64_t now = engram_now_ms();
for(int b=0;b<nb;b++){
EngramNode* t=&g->nodes[best_idx[b]];
if(eg_edge_exists_between(g, ise->id, t->id)) continue; /* dedup guard */
engram_grow_edges();
EngramEdge* ne=&g->edges[g->edge_count];
memset(ne,0,sizeof(*ne));
ne->id = engram_new_id();
ne->from_id = el_strdup_persist(ise->id);
ne->to_id = el_strdup_persist(t->id);
ne->relation = el_strdup_persist("hebbian-associate");
ne->metadata = el_strdup_persist("{\"origin\":\"consolidated-from-ISE\"}");
ne->weight = ENGRAM_HEBB_LINK_W0;
ne->hebb = ENGRAM_HEBB_ETA; /* nonzero so the trace can rehearse */
ne->confidence= 1.0;
ne->created_at= now; ne->updated_at= now; ne->last_fired= now;
ne->layer_id = ENGRAM_LAYER_DEFAULT;
g->edge_count++;
engram_adj_on_edge_added(g, g->edge_count-1);
eg_hebb_wb_push(ne->from_id, ne->to_id, ne->weight, ne->hebb);
}
}
/* P1 PERMANENCE threshold (design §9). Promote a node past the higher bar:
* mark it durable (metadata provenance "consolidated-from-ISE") so the 48h
* telemetry prune no longer sweeps it, and mirror to the durable store. The
* caller (soul) decides WHEN to attempt promotion (rehearsal / re-activation);
* this primitive enforces the bar on the node's ACT-R base-level and is
* idempotent (no double-promote). Returns 1 if the node is durable after the
* call, else 0. Reversible: clear the marker to demote. Inert unless
* ENGRAM_CONSOLIDATION is set. */
el_val_t engram_consolidate_permanence(el_val_t node_id){
if(!eg_consolidation_on()) return (el_val_t)(int64_t)0;
EngramNode* n = engram_find_node(EL_CSTR(node_id));
if(!n) return (el_val_t)(int64_t)0;
if(eg_node_is_durable(n)) return (el_val_t)(int64_t)1; /* already durable */
double bl = engram_bll_base_level(n, engram_now_ms());
if(bl < eg_consol_perm_min()) return (el_val_t)(int64_t)0; /* below permanence bar */
free(n->metadata);
n->metadata = el_strdup_persist("{\"origin\":\"consolidated-from-ISE\",\"durable\":true}");
n->updated_at = engram_now_ms();
if(engram_store_enabled()) eg_store_put_node(n);
return (el_val_t)(int64_t)1;
}
/* engram_temporal_decay — recency shaping on the activation path.
*
* MEASURED FAILURE (2026-08-05 self-review). Census of the live graph under
+1
View File
@@ -622,6 +622,7 @@ el_val_t engram_search_json(el_val_t query, el_val_t limit);
el_val_t engram_scan_nodes_json(el_val_t limit, el_val_t offset);
el_val_t engram_scan_nodes_by_type_json(el_val_t node_type, el_val_t limit, el_val_t offset);
el_val_t engram_scan_nodes_emb_json(el_val_t limit, el_val_t offset);
el_val_t engram_consolidate_permanence(el_val_t node_id);
el_val_t engram_neighbors_json(el_val_t node_id, el_val_t max_depth, el_val_t direction);
el_val_t engram_activate_json(el_val_t query, el_val_t depth);
el_val_t engram_stats_json(void);
+4
View File
@@ -1090,6 +1090,10 @@ el_val_t __engram_scan_nodes_emb_json(el_val_t limit, el_val_t offset) {
return engram_scan_nodes_emb_json(limit, offset);
}
el_val_t __engram_consolidate_permanence(el_val_t node_id) {
return engram_consolidate_permanence(node_id);
}
el_val_t __engram_neighbors_json(el_val_t node_id, el_val_t max_depth, el_val_t direction) {
return engram_neighbors_json(node_id, max_depth, direction);
}