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.
This commit is contained in:
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user