Bring the relational-neighborhood geometry OPERATORS from the viz proxy
(engram-geometry-proxy.py §5) into the C runtime as reusable primitives, and
expose each as an EL builtin so any CGI app / el program can use them — not just
the engram service internals.
engram_geometry.{h,c} (pure, libm-only, read-only over descriptors):
- engram_geo_overlap : shared-member Jaccard + centroid/scale proximity
score + intersection centroid.
- engram_geo_subtract : orthogonal-complement residual (project A onto
I - V_B V_Bᵀ), closed-form variance_explained_by_B,
residual ellipsoid + centroid-diff; set-diff variant.
- engram_geo_combine : pooled descriptor (exact law-of-total-variance mean +
covariance), re-eigendecomposed.
- engram_geo_distance : centroid L2 + cosine + closed-form Wasserstein-2
(Bures) — mirrors the proxy _wasserstein2.
- engram_geo_analogy : orthogonal Procrustes R = UVᵀ (SVD) aligning A's
principal frame to B's + apply helper.
The C descriptor is full-dim/centered with a low-rank covariance from its top
axes; operators mirror the proxy FORMULAS and do the Wasserstein/combine eigen
work inside the small joint-axis subspace (exact there). Reuses jacobi_sym.
EL builtins (el_runtime.{h,c}, el_seed.c native wrappers):
engram_geo_{descriptor,overlap,subtract,combine,distance,analogy}_json —
take comma-separated seed-id set(s), build the CENTERED descriptor against the
true store-wide mean (ad-hoc path), run the operator, return JSON. Additive:
no flag, no effect on activation/retrieval. Surfacing via engram.el + the elc
fold is a cutover step (same elc-drift deferral as the P0/P5 builtins); the C
table wiring is registered now.
Tested: synthetic closed-form unit suite (20/20) — Wasserstein, Jaccard/score,
orthogonal residual, set-diff, pooled combine, Procrustes recovery. ASan+UBSan
clean; 0 leaks. Read-only; no activation/retrieval behavior change.
Adds a read-only builtin that returns the curiosity_scan InternalStateEvents
created after a `since` cutoff that are STILL RESIDENT — "what I was chewing on
while you were gone." curiosity_scan is identified by the marker the soul writes
into each ISE's JSON content; heartbeat and other ISEs are excluded.
HARD honesty rail: it reports only ISEs still in the buffer. Anything rotated
out by the 48h engram_prune_telemetry is simply ABSENT — rotated-out = "I don't
remember", never a synthesized/plausible dream. Purely additive, no flag.
The HTTP route (GET /api/dreams?since=) is DEFERRED to cutover per the elc-drift
blocker (regenerating engram/dist diverges with no source change); the builtin
is exercised directly by the pure-C gate.
MEASURED on a copy: seeded 3 curiosity_scan (ancient/1h/now) + 1 heartbeat;
before prune dreams returned exactly the 3 curiosity_scan (heartbeat excluded);
after the 48h prune the ancient one was ABSENT (not confabulated), leaving 2;
the since-filter returned only the post-cutoff event; no returned id was ever
fabricated. ASan+UBSan clean.
The felt passage of time is the cooling of the activation field, not a tick
count and not an elapsed-seconds readout. engram_age_field(delta_ms) cools the
field (working_memory_weight + background_activation) by the caller's MEASURED
wall-clock delta with a pure exponential exp(-dt/TC) — no per-call floor — so it
is exactly scale-invariant: N ticks summing to the same elapsed time produce the
same total cooling. It returns the cooling MAGNITUDE (1-exp(-dt/TC), a bounded
[0,1) drift signal), never elapsed seconds.
Reboot = anesthesia: a global last-tick wall-clock stamp is persisted to a
sidecar (chrono_last_tick) in the data dir. engram_age_field_catchup() reads it
on boot, applies ONE cooling for the whole unconscious gap, refreshes the stamp,
and reports the magnitude — timestamps are bookkeeping to COMPUTE the drift,
never the felt signal. TC env-tunable via ENGRAM_CHRONO_TC (default 3600s).
All inert unless ENGRAM_CHRONOCEPTION is set → OFF path byte-identical.
MEASURED on a copy (throwaway HOME, TC=3600s):
- Cooling scales with dt, matching 1-exp(-dt/TC) to 1e-6: dt=600s->0.1535,
1800s->0.3935, 3600s->0.6321, 7200s->0.8647.
- Scale-invariance EXACT: age(dt) once vs age(dt/N) N times gives identical
field sum (|delta|=0.0) for N=2, 10, 100.
- Reboot catch-up over a 1h gap cooled the field 0.60->0.4415 in one shot,
magnitude 0.6321, bounded in [0,1).
- Flag OFF: age & catchup return 0, field untouched (sum 1.2).
ASan+UBSan clean.
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.
Read routes (GET /api/embeddings, /api/graph/dump) need node embedding
vectors, but every consumer emit path deliberately drops the ~5.7KB emb
vector (include_emb=0) to stay under MCP token limits. Rather than perturb
that shared path, add a dedicated additive builtin that pages nodes WITH
their dense vector, emitting id/node_type/label/created_at/emb_dim plus emb
as a JSON array whose length equals emb_dim (so a consumer can verify the
vector round-trips). Un-embedded nodes emit emb_dim:0 / emb:[]. Same
salience-sorted, transparent-layer-skipped, bounded pagination as
engram_scan_nodes_json; default page 256.
Purely additive: engram_emit_node_json and the default include_emb=0 are
untouched, so every existing endpoint is byte-identical to trunk (verified:
scan_nodes_json still carries no emb). The HTTP route wiring in server.el is
DEFERRED to cutover per the elc-drift blocker (regenerating engram/dist
diverges ~285 lines with no source change); the builtin is exercised
directly by the pure-C gate instead.
Measured on a copy: len(emb)==emb_dim for all nodes, pagination disjoint,
existing path unchanged; full 256-node x 768-dim page = 16.7 ms / 1.18 MB.
ASan+UBSan clean.
- Wire paged store into the ENGRAM SERVICE (server.el, the authoritative durable
owner): boot->engram_store_boot, persist_canonical->engram_store_checkpoint,
gated by ENGRAM_STORE.
- elc (lang/elc.c + src/parser.el + codegen.el + elc-combined.el): OOB guard in
tok_kind/tok_value + parse_block progress backstop — fixes the pre-existing
unbounded-memory fold hang on sessions.el.
- engram_prune_telemetry mirrors ISE prune to the store (store_forget) so store
live-count tracks resident and stale telemetry stays bounded.
- Deployed live 2026-08-12: engram :8742 on neuron.egm+WAL, count reconciled 11552.
Establish lang/runtime/ as the ONE canonical el runtime (from the active
runtime that carries hebb/emb persistence + the new WAL); repoint the el CI
publish, engram build, elb default, and in-repo build scripts to it; delete
the el-compiler/runtime + lang/releases/ forks; add scripts/check-single-runtime.sh
drift guard.
Fixes a live prod bug: the el CI published el-runtime-c/-h from the LAGGING
el-compiler fork (0 hebb refs), so the shipped soul never persisted Hebbian
edge weights — learned co-activation was wiped on every restart. Publishing
from canonical ships the stranded 'learning that cannot outlive the process'
fix.
WAL storage engine + integrity fixes (DELETE->tombstone + store-layer
protection, safe data-dir default) ride in behind ENGRAM_WAL (default off =
byte-identical to today). Verified: engram elb per-module build clean, WAL
gate 66/66, native smoke ok, drift-guard green.