runtime: anchor the think read, so Neuron can think at all #142

Merged
will.anderson merged 1 commits from fix/think-anchor into dev 2026-08-16 16:26:01 +00:00
Owner

engram_think_json passed NULL as the anchor. 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 → every axis projection 0 → grad 0 → the "at rest" branch at engram_cognition.c:137.

Measured consequence. Every faculty returned an identical null result, differing only in its label:

{"direction":[0,0,0,0,0,0,0,0],"spread":0,"magnitude":1,"confidence":0.5}

magnitude 1 is membership evaluated at the centroid, spread 0 is its distance to itself, confidence 0.5 is the stance fallback. Every observed number is explained by the NULL.

The geometry was never at fault. /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.

Fix. The seeds choose which region; they must also supply the vantage. Anchor at the first resolvable embedded seed — the same seed eg_geo_build_desc infers dim from, so the two can never disagree. A single seed still yields a real gradient, because the descriptor expands to that seed’s neighbourhood and the seed’s own position is distinct from the neighbourhood centroid. The vector is copied, not borrowed: g->nodes is realloc’d in place on append, so a borrowed EngramNode* dangles across a concurrent write.

Verified against a clone of the production store (13,616 nodes / 37,865 edges):

seed n_support magnitude spread
self anchor 87 0.00282 18.79
values hub 28 0.00318 17.72

with distinct unit direction vectors. Previously both returned the zero vector, magnitude 1, spread 0.

Still open, and isolated by this fix: all five faculties still return identical numbers and confidence stays 0.5, because cog_stance_init is passed NULL for the stance and the faculty enters the computation only through the stance’s axis_gain[] and bias_dir. The faculty label is inert until a stance is loaded — which is exactly what learn()’s correspondence-beat calibrates. Same shape as this bug: a neutral parameter collapsing a capability to a constant.

`engram_think_json` passed `NULL` as the anchor. 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` → every axis projection 0 → `grad` 0 → the "at rest" branch at `engram_cognition.c:137`. **Measured consequence.** Every faculty returned an identical null result, differing only in its label: ``` {"direction":[0,0,0,0,0,0,0,0],"spread":0,"magnitude":1,"confidence":0.5} ``` `magnitude 1` is membership evaluated at the centroid, `spread 0` is its distance to itself, `confidence 0.5` is the stance fallback. Every observed number is explained by the NULL. **The geometry was never at fault.** `/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. **Fix.** The seeds choose *which* region; they must also supply the *vantage*. Anchor at the first resolvable embedded seed — the same seed `eg_geo_build_desc` infers `dim` from, so the two can never disagree. A single seed still yields a real gradient, because the descriptor expands to that seed’s neighbourhood and the seed’s own position is distinct from the neighbourhood centroid. The vector is **copied, not borrowed**: `g->nodes` is realloc’d in place on append, so a borrowed `EngramNode*` dangles across a concurrent write. **Verified** against a clone of the production store (13,616 nodes / 37,865 edges): | seed | n_support | magnitude | spread | |---|---|---|---| | self anchor | 87 | 0.00282 | 18.79 | | values hub | 28 | 0.00318 | 17.72 | with distinct unit direction vectors. Previously both returned the zero vector, magnitude 1, spread 0. **Still open, and isolated by this fix:** all five faculties still return identical numbers and `confidence` stays 0.5, because `cog_stance_init` is passed NULL for the stance and the faculty enters the computation *only* through the stance’s `axis_gain[]` and `bias_dir`. The faculty label is inert until a stance is loaded — which is exactly what `learn()`’s correspondence-beat calibrates. Same shape as this bug: a neutral parameter collapsing a capability to a constant.
will.anderson added 1 commit 2026-08-16 16:25:41 +00:00
runtime: anchor the think read, so Neuron can think at all
El SDK CI - dev / build-and-test (pull_request) Failing after 13m24s
ded6ca546f
engram_think_json passed NULL as the anchor. 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 at
engram_cognition.c:137.

Measured consequence: EVERY faculty returned an identical null result,
differing only in its label —
  {"direction":[0,0,0,0,0,0,0,0],"spread":0,"magnitude":1,"confidence":0.5}
magnitude 1 is membership evaluated at the centroid, spread 0 is its
distance to itself, confidence 0.5 is the stance fallback. The geometry was
never at fault: /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. Anchor at
the first resolvable embedded seed — the same seed eg_geo_build_desc infers
dim from, so the two can never disagree. One seed still yields a real
gradient because the descriptor expands to that seed's neighbourhood, so
the seed's position is distinct from the neighbourhood centroid.

The vector is COPIED, never borrowed: g->nodes is realloc'd in place on
append, so a borrowed EngramNode* dangles across any concurrent write.

Verified against a clone of the production store (13,616 nodes / 37,865
edges):
  self anchor   n_support 87  magnitude 0.00282  spread 18.79
  values hub    n_support 28  magnitude 0.00318  spread 17.72
with distinct unit direction vectors. Previously both returned the zero
vector with magnitude 1 and spread 0.

STILL OPEN, now isolated by this fix: all five faculties return identical
numbers and confidence stays 0.5, because cog_stance_init is passed NULL
for the stance and the faculty enters the computation only through the
stance's axis_gain[] and bias_dir. The faculty label is inert until a
stance is loaded — which is what learn()'s correspondence-beat calibrates.
Same shape as this bug: a neutral parameter collapsing a capability to a
constant.
will.anderson merged commit 44b621e551 into dev 2026-08-16 16:26:01 +00:00
Sign in to join this conversation.