runtime: anchor the think read, so Neuron can think at all (#142)
El SDK CI - dev / build-and-test (push) Failing after 13m0s

This commit was merged in pull request #142.
This commit is contained in:
2026-08-16 16:26:00 +00:00
+59 -1
View File
@@ -13775,7 +13775,65 @@ el_val_t engram_think_json(el_val_t seeds, el_val_t faculty) {
if (!g) return eg_geo_err("geometry unavailable");
CogStance st; cog_stance_init(&st, NULL, EL_CSTR(faculty), g->hub_id, NULL, g);
GeoGradient grad;
if (engram_think(g, NULL, &st, &grad) != 0) { cog_stance_free(&st); engram_geo_free(g); return eg_geo_err("think failed"); }
/* ANCHOR THE READ (2026-08-16 self-review). This passed NULL, and NULL is
* not "no opinion" engram_think re-origins at `anchor ? anchor :
* region->centroid`, so NULL means "read from the centroid", and the
* centroid is the ONE point where the gradient is zero by construction:
* r = x - centroid = 0, so every axis projection is 0, grad is 0, and
* direction takes the "at rest" branch. Measured consequence: EVERY
* faculty reason, abduce, induce, plan, analogize returned an
* identical null result, differing only in its label:
* {"direction":[0,0,...],"spread":0,"magnitude":1,"confidence":0.5}
* magnitude 1 is membership evaluated at the centroid, spread 0 is its
* distance to itself, and confidence 0.5 is the stance fallback. The
* geometry was never the problem /api/drift computes real values
* (centroid_sep 0.104, core_disp 0.045) over the very same 87 members.
* Neuron could not think because the read was always taken from the
* region's own centre.
*
* The seeds choose WHICH region; they must also supply the VANTAGE it is
* read from. Anchor at the first resolvable embedded seed the same seed
* eg_geo_build_desc infers `dim` from, so the two never disagree. A single
* seed still yields a real gradient because the descriptor expands to the
* seed's neighbourhood (87 members for the self anchor), so the seed's own
* position is distinct from the neighbourhood centroid.
*
* COPY the vector, never borrow it: g->nodes is realloc'd in place on
* append, so a borrowed EngramNode* is a dangling pointer across any
* concurrent write. 768 floats is 3 KB. */
float* anchor = NULL;
{
EngramStore* eg = engram_get();
const char* csv = EL_CSTR(seeds);
if (eg && csv) {
const char* p = csv;
while (*p && !anchor) {
while (*p == ' ' || *p == ',') p++;
const char* s = p;
while (*p && *p != ',') p++;
const char* e = p; while (e > s && e[-1] == ' ') e--;
if (e > s) {
char* id = strndup(s, (size_t)(e - s));
if (id) {
int64_t idx = engram_find_node_index(id);
if (idx >= 0 && idx < eg->node_count) {
EngramNode* n = &eg->nodes[idx];
if (n->emb && n->emb_dim == g->dim) {
anchor = malloc(sizeof(float) * (size_t)g->dim);
if (anchor) memcpy(anchor, n->emb,
sizeof(float) * (size_t)g->dim);
}
}
free(id);
}
}
}
}
}
if (engram_think(g, anchor, &st, &grad) != 0) { free(anchor); cog_stance_free(&st); engram_geo_free(g); return eg_geo_err("think failed"); }
free(anchor);
JsonBuf b; jb_init(&b); char t[256];
snprintf(t, sizeof t, "{\"faculty\":\"%s\",\"n_support\":%d,\"magnitude\":%.6g,\"spread\":%.6g,\"confidence\":%.6g,\"dim\":%d",
EL_CSTR(faculty), grad.n_support, grad.magnitude, grad.spread, grad.confidence, grad.dim);