From 7946b98d3ddc1952a0919a1e0eee170bec59997e Mon Sep 17 00:00:00 2001 From: Will Anderson Date: Wed, 12 Aug 2026 20:29:16 -0500 Subject: [PATCH] M9: env-gated geometry priming in engram_activate (ENGRAM_GEOMETRY_PRIMING, default OFF) Wire the centered relational-neighborhood geometry (engram_geometry.c) into activation seed selection behind a reversible env flag that defaults OFF. Flag unset => byte-identical to M8 (verified: identical result id sequence + order across 15 queries vs the M8 baseline binary). When set, composes with M8's ANN candidate generation: damp-only seed reweight by centered membership (disambiguation) + sub-threshold neighborhood priming (warm floor below the WM gate, capped, ISE-skipped). Safe because the BFS keeps the max, so priming only raises a floor and can never cap a legitimate activation. Descriptor + global mean run over the paged store; the resident-array vindex is bridged with a vids[] map. Tunables via env (SEED_LO/PRIME_SCALE/PRIME_MAX). Default-OFF binary is behavior-neutral and safe to deploy. Enabling the flag is currently NO-GO on cost/benefit: 3.2x median / 13x p90 latency for no reliable coherence/disambiguation gain (see perf profile). Not a defect - WM cap holds, no crash, ASan/UBSan clean. --- lang/runtime/el_runtime.c | 154 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) diff --git a/lang/runtime/el_runtime.c b/lang/runtime/el_runtime.c index a40a501..ec0db33 100644 --- a/lang/runtime/el_runtime.c +++ b/lang/runtime/el_runtime.c @@ -6540,6 +6540,9 @@ static int64_t _eg_act_wm_evicted = 0; /* ALL WM evictions, cumulative (see b * candidate's content. Both cumulative for the process lifetime. */ static int64_t _eg_act_dup_seeds = 0; static int64_t _eg_act_dup_wm = 0; +/* M9 geometry priming: sub-threshold neighborhood members primed by the centered + * geometry (ENGRAM_GEOMETRY_PRIMING). Cumulative; stays 0 when the flag is off. */ +static int64_t _eg_act_geo_primed = 0; /* Redundant WM residents evicted by the GLOBAL pass (2026-08-06). Counted * separately from _eg_act_dup_wm on purpose: dup_wm measures duplicates caught * among this call's candidates, dup_wm_global measures duplicates that reached @@ -7433,6 +7436,7 @@ static char* engram_first_n_chars(const char* s, size_t n) { * ══════════════════════════════════════════════════════════════════════════ */ #include "engram_store.h" #include "engram_vindex.h" /* M8: ANN (HNSW) index for activation seed selection */ +#include "engram_geometry.h" /* M9: centered relational-neighborhood geometry (priming) */ static EngramPagedStore* g_engram_store = NULL; @@ -9016,6 +9020,62 @@ static VIndex* eg_vindex_sync(EngramStore* g, int32_t dim) { return _eg_vindex; } +/* ── M9 GEOMETRY PRIMING (ENGRAM_GEOMETRY_PRIMING, default OFF) ────────────── + * Opt-in wiring of the centered relational-neighborhood geometry (engram_geometry.c) + * into activation seed selection. When the flag is UNSET or "0" every code path + * below is skipped and engram_activate is byte-identical to M8. When set, after + * M8 has produced its ANN seed set, the centered geometry of that neighborhood is + * used to (a) DAMP off-domain seeds by centered membership (disambiguation) and + * (b) PRIME nearby neighborhood members sub-threshold (warm floor). It COMPOSES + * with M8 — it never removes an M8 seed nor changes ANN candidate discovery. + * + * The geometry descriptor + global-mean run over the PAGED store (g_engram_store) + * by string id; the runtime's resident-array VIndex is passed through with a + * vids[] map (vids[i] == g->nodes[i].id) so its ordinals resolve. This is the + * behaviour-changing M9 step gated behind a reversible flag — see runbook + * 2026-08-12-geometry-priming-cutover-reversal.md. */ +static int eg_geometry_priming_on(void) { + static int cached = -1; + if (cached < 0) { + const char* s = getenv("ENGRAM_GEOMETRY_PRIMING"); + cached = (s && s[0] && s[0] != '0') ? 1 : 0; + } + return cached; +} + +/* Runtime-owned centered-frame global mean over the paged store's embedded set. + * Built lazily on first priming call, recomputed only when the embedded count + * drifts >10% (engram_geo_mean_maybe_refresh). Process-lifetime, single-threaded, + * alongside _eg_vindex. Returns NULL if unavailable (no paged store / no embeds / + * dim mismatch) → caller falls back to pure-M8 behaviour for that call. */ +static GeoMeanCache* _eg_geo_mean = NULL; +static const float* eg_geo_mean_sync(int32_t dim) { + if (!g_engram_store || dim <= 0) return NULL; + if (!_eg_geo_mean) { + _eg_geo_mean = engram_geo_mean_build(g_engram_store); + if (!_eg_geo_mean) return NULL; + } else { + (void)engram_geo_mean_maybe_refresh(_eg_geo_mean, g_engram_store, 0.10); + } + if (engram_geo_mean_dim(_eg_geo_mean) != dim) return NULL; /* embedder dim moved */ + return engram_geo_mean_vec(_eg_geo_mean); +} + +/* Geometry-priming tunables (all bounded so the flag can only SHARPEN, never + * amplify or overflow WM). Overridable via env for the A/B without a rebuild. */ +static double eg_geo_seed_lo(void) { /* seed damp floor: factor in [LO,1] */ + const char* s = getenv("ENGRAM_GEO_SEED_LO"); double v = s ? atof(s) : 0.5; + if (!(v >= 0.0 && v <= 1.0)) v = 0.5; return v; +} +static double eg_geo_prime_scale(void){ /* primed warm act = membership*scale (< WM gate) */ + const char* s = getenv("ENGRAM_GEO_PRIME_SCALE"); double v = s ? atof(s) : 0.08; + if (!(v > 0.0 && v < ENGRAM_WM_THRESHOLD)) v = 0.08; return v; +} +static int eg_geo_prime_max(void){ /* cap primed members added to the frontier */ + const char* s = getenv("ENGRAM_GEO_PRIME_MAX"); int v = s ? atoi(s) : 32; + if (v < 0) v = 0; if (v > 256) v = 256; return v; +} + el_val_t engram_activate(el_val_t query, el_val_t depth) { EngramStore* g = engram_get(); const char* q = EL_CSTR(query); @@ -9308,6 +9368,100 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { sel[nsel] = bi; selkey[nsel] = key; nsel++; } free(seed_dup); + + /* ── M9 GEOMETRY PRIMING (ENGRAM_GEOMETRY_PRIMING, default OFF) ────── + * COMPOSES with the M8 seed set above: uses the CENTERED geometry of + * the seed neighborhood to (a) damp off-domain seeds by centered + * membership (disambiguation) and (b) prime nearby members sub- + * threshold (a warm floor). Flag OFF → this whole block is skipped and + * the seed set/activation are exactly what M8 produced. Read-only over + * the graph except for the bounded, sub-threshold seed additions here. */ + if (eg_geometry_priming_on() && g_engram_store && q_emb && q_dim > 0 && nsel > 0) { + const float* gmean = eg_geo_mean_sync(q_dim); + if (gmean) { + /* Seed ids = the M8-selected semantic seeds; vids maps the + * resident-array VIndex ordinals (== g->nodes[] index) to store + * ids so the descriptor's ANN expansion resolves to paged nodes. */ + const char** seed_ids = malloc((size_t)nsel * sizeof(char*)); + char** vids = malloc((size_t)g->node_count * sizeof(char*)); + if (seed_ids && vids) { + for (int s = 0; s < nsel; s++) seed_ids[s] = g->nodes[sel[s]].id; + for (int64_t i = 0; i < g->node_count; i++) vids[i] = g->nodes[i].id; + GeoDescriptor* geo = engram_geometry_descriptor( + g_engram_store, _eg_vindex, vids, (int)g->node_count, + seed_ids, (size_t)nsel, NULL, gmean); + if (geo && geo->n_members > 0) { + const double lo = eg_geo_seed_lo(); + const double pscl = eg_geo_prime_scale(); + const int pmax = eg_geo_prime_max(); + /* Centered membership per resident idx (-1 = not in the + * geometry → left untouched by the reweight). */ + double* geo_m = malloc((size_t)g->node_count * sizeof(double)); + if (geo_m) { + for (int64_t i = 0; i < g->node_count; i++) geo_m[i] = -1.0; + for (int m = 0; m < geo->n_members; m++) { + int64_t ri = engram_find_node_index(geo->members[m].id); + if (ri >= 0 && ri < g->node_count) { + double mv = geo->members[m].membership; + if (mv < 0.0) mv = 0.0; else if (mv > 1.0) mv = 1.0; + geo_m[ri] = mv; + } + } + /* (a) DAMP-ONLY seed reweight: factor = lo+(1-lo)*memb + * ∈ [lo,1]. Off-domain seeds (low centered membership) + * lose weight; the neighborhood anchor (memb→1) is + * unchanged. Never amplifies. Updates both the frontier + * act (drives propagation) and best_bg (drives this + * node's own WM weight). */ + for (int64_t s = 0; s < seed_count; s++) { + int64_t si = seeds[s].idx; + if (si < 0 || si >= g->node_count) continue; + double mv = geo_m[si]; + if (mv < 0.0) continue; /* not in geometry */ + double factor = lo + (1.0 - lo) * mv; + seeds[s].act *= factor; + best_bg[si] *= factor; + } + /* (b) PRIME sub-threshold: descriptor members not + * already reached get a warm floor act=memb*pscl + * (pscl < WM gate ⇒ cannot self-promote) and enter the + * frontier so a warm gradient spreads one hop then dies + * at the 0.02 BFS cutoff. Capped at pmax; ISE skipped. + * Safe: BFS keeps max, so this only RAISES a floor and + * never caps a stronger legitimate activation. */ + int primed = 0; + for (int m = 0; m < geo->n_members && primed < pmax; m++) { + int64_t ri = engram_find_node_index(geo->members[m].id); + if (ri < 0 || ri >= g->node_count) continue; + if (reached[ri]) continue; /* already a seed */ + EngramNode* pn = &g->nodes[ri]; + if (pn->node_type && + strcmp(pn->node_type, "InternalStateEvent") == 0) + continue; + double mv = geo->members[m].membership; + if (mv < 0.0) mv = 0.0; else if (mv > 1.0) mv = 1.0; + double pact = mv * pscl; + if (pact < 0.01) continue; /* too cold to matter */ + seeds[seed_count].idx = ri; + seeds[seed_count].act = pact; + seeds[seed_count].created_at = pn->created_at; + seed_count++; + best_bg[ri] = pact; + best_hops[ri] = 0; + reached[ri] = 1; + primed++; + } + _eg_act_geo_primed += primed; + free(geo_m); + } + engram_geo_free(geo); + } else if (geo) { + engram_geo_free(geo); + } + } + free(seed_ids); free(vids); + } + } } free(e_eff); e_eff = NULL; /* M8: no longer needed past seed selection */ /* Compute mean seed created_at for temporal proximity bonus.