Files
el/engram/test/test_verify.c
T
bigmerge bacaf3d39c
El SDK CI - dev / build-and-test (pull_request) Failing after 4m49s
engram: reconcile M8 HNSW vindex (#109) onto current dev, restore 3 fixes the branch predated
Lands feat/reframe-region-setop (PR #109: native set-based reframe_region,
decorator-as-seam @route port, teacher-summon, and the M8.1 activate-latency
work — lazy-memoized cosq via eg_cosq_at + engram_vindex HNSW-accelerated
seed discovery + vindex_harvest_from_store/vindex_bench oracle) onto dev's
actual current HEAD, plus engram-tiered-storage's still-unique test suite.

RECONCILING #109 WITH engram-tiered-storage (M4-M10 HNSW/geometry/reason/
verify work): not a two-way merge. engram_vindex.c's HNSW core (search_layer/
select_neighbors/prune_links/insert) is BYTE-IDENTICAL between the two
branches; #109's copy is a strict superset (adds vindex_harvest_from_store,
used by vindex_bench.c's brute-force-vs-HNSW oracle). engram_reason.c and
engram_verify.c are also byte-identical. #109's own branch point already
carried engram-tiered-storage's M4-M10 lineage forward, so there was nothing
left to merge into #109 for those files. The one thing engram-tiered-storage
had that #109's tree dropped: its full test suite (test_vindex.c,
test_geometry.c, test_reason.c, test_verify.c, test_m7_traversal.c, the
interoception P0-P5 tests, bufpool/compaction tests, and their run_*.sh
harnesses) — ported over here unchanged.

WHY THIS NEEDED HAND RECONCILIATION, NOT A MECHANICAL MERGE: #109's branch
forked from dev on 2026-08-14 15:40 (before restructure-adjacent history
diverged the file's merge-base for `git merge` — it presented as an add/add
conflict). A straight two-dot diff (dev tip -> PR tip) applied cleanly, but
it silently reverted THREE dev fixes landed on 2026-08-14/15, after the
branch point, that the PR's diff had no way to know about:

  1. qgate rescale (2026-08-14 self-review): PR's lazy eg_cosq_at rewrite of
     the query-aware propagation gate dropped the shift-and-floor rescale
     about ENGRAM_EMBED_S0 (measured: unrelated-pair median 0.562->raw gate
     0.67, i.e. "a small tax, not a gate"). Restored the rescale, wrapped
     around the lazy accessor -- the PR's actual improvement (WHEN cosq[oi]
     is computed) is orthogonal to WHAT it gates on and both are kept.
  2. Eviction cause decomposition (2026-08-14 self-review): dev decomposes
     wm_evicted into evict_floor/evict_cap/evict_bll so WM churn is
     diagnosable (identity: evicted == floor+cap+bll+dup_wm+dup_wm_global).
     PR's tree predates this and dropped all three counters + their JSON
     stats fields. Restored declarations, all 4 direct increment sites, the
     eg_wm_carry_over bll increment, and the act-stats JSON fields --
     alongside (not instead of) the PR's own P4 afferent / API-reshape
     counters already in that same struct/JSON.
  3. Hebbian link-formation selection (2026-08-15 self-review, TODAY): dev
     selects the STRONGEST qualifying candidate for consolidation each call;
     PR's tree predates this and reverted to hash-slot order (arbitrary wrt
     association strength) for edge formation -- the one path that writes
     PERMANENT structure. Restored the strongest-candidate while-loop,
     keeping the PR's own genuine improvement at that site
     (engram_adj_on_edge_added incremental-index append instead of a bare
     adj_dirty=1 full-rebuild flag).

engram/src/server.el's 3-way conflicts (autoconnect_on/ise_offgraph_on env
flags, /api/nodes connected-count in responses) were pure additive: dev's
side was empty, PR's side added the feature. Took PR's side whole.

VERIFIED (nsbx sandbox only, live :8742/:7770 never touched):
  - cc -std=c11 -O2, clean link against the real engram/src/server.el via
    elc, zero errors.
  - vindex_bench (built standalone, read-only harvest) against the real
    production store clone (13,671 embedded nodes, 768-dim nomic-embed-text):
    recall@10 = 1.0000 at ef 64/128/200; HNSW search 0.28-0.79ms/query vs
    2.03ms/query brute-force oracle (2.6x-7.2x). HNSW build itself: 46.5s
    for the full 13,671-node set -- see the flagged risk below.
  - Booted the reconciled binary in an isolated nsbx sandbox (:8905, cloned
    snapshot of the live store, 13,424 nodes / 37,656 edges) and called
    /api/activate for real: first call after boot 41.5s (pays the one-time
    HNSW build inline -- matches the standalone bench), second/third calls
    356ms/605ms, no crash, correct results, act-stats JSON (including the
    restored evict_floor/cap/bll fields) reads correctly.

KNOWN RISK TO FLAG BEFORE ANY LIVE CUTOVER (not fixed here; out of scope for
this dev-only land per instructions not to touch :8742/:7770): eg_vindex_sync
builds the HNSW index synchronously, inline, on the first engram_activate()
call after every process start (or index invalidation). On the real node
count that is a ~46s blocking stall on a single-threaded server -- the first
request after every restart (or its concurrent siblings) waits the full
build. Recommend a background/incremental build (or a bounded per-call build
budget) before this ever reaches the live daemon. See PR description / final
report for the fuller writeup.
2026-08-15 16:46:44 -05:00

245 lines
13 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* Closed-form unit tests for the VERIFIER layer (engram_verify.c). Every case is a
* hand-built synthetic descriptor / claim point whose verdict is known in closed
* form — the checks are PROVEN, not declared. ASan/UBSan target.
*
* The headline case is CONSISTENCY's polarity check: the reassurance→accusation
* inversion ("you never fought" → "you argued") that no grammar check catches. */
#include "engram_verify.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
static int failures = 0, checks = 0;
static void ok(const char* what, int cond) {
checks++;
if (!cond) { failures++; printf(" FAIL: %s\n", what); }
else printf(" ok: %s\n", what);
}
static void approx(const char* what, double got, double exp, double tol) {
ok(what, fabs(got - exp) <= tol);
if (fabs(got - exp) > tol) printf(" got=%.9g exp=%.9g\n", got, exp);
}
/* ── descriptor builder (mirrors test_reason.c) ─────────────────────────────── */
static float* vec(const double* v, int dim) {
float* f = malloc((size_t)dim * sizeof(float));
for (int i = 0; i < dim; i++) f[i] = (float)v[i];
return f;
}
static GeoDescriptor* mk(int dim, const double* centroid,
int n_axes, const double* axis_flat, const double* extents,
int n_members, const char** ids, double total_var) {
GeoDescriptor* g = calloc(1, sizeof(GeoDescriptor));
g->dim = dim;
g->centroid = centroid ? vec(centroid, dim) : NULL;
g->global_mean = NULL;
g->n_axes = n_axes;
g->axes = n_axes ? calloc((size_t)n_axes, sizeof(GeoAxis)) : NULL;
double tr = 0;
for (int k = 0; k < n_axes; k++) {
g->axes[k].axis = vec(&axis_flat[(size_t)k * dim], dim);
g->axes[k].extent = extents[k];
tr += extents[k] * extents[k];
}
g->total_variance = (total_var >= 0) ? total_var : tr;
g->radius = sqrt(g->total_variance > 0 ? g->total_variance : 0);
g->n_members = n_members; g->n_embedded = n_members;
g->members = n_members ? calloc((size_t)n_members, sizeof(GeoMember)) : NULL;
for (int i = 0; i < n_members; i++) {
g->members[i].id = strdup(ids[i]);
g->members[i].membership = 1.0;
g->members[i].centrality = (double)(n_members - i);
g->members[i].embedded = 1;
}
g->hub_id = n_members ? strdup(ids[0]) : strdup("");
g->k_core = 1; g->co_registration = 0.0; g->n_edges = 0; g->edges = NULL;
return g;
}
int main(void) {
printf("== VERIFIER layer unit tests ==\n");
/* ══════════════════ GROUNDING — supported vs floating (hallucination) ════ */
/* Two real neighborhoods: E0 at origin, E1 far along e0. A claim planted inside
* E0 is grounded; a claim floating far off-manifold (along an unmodeled axis) is
* flagged UNGROUNDED; a claim near E1 grounds to E1, not E0. */
{
int dim = 4;
double c0[4] = {0,0,0,0}, c1[4] = {10,0,0,0};
double ax[8] = {1,0,0,0, 0,1,0,0}; double ex[2] = {1,1};
const char* i0[1] = {"E0"}, *i1[1] = {"E1"};
GeoDescriptor* E0 = mk(dim, c0, 2, ax, ex, 1, i0, -1);
GeoDescriptor* E1 = mk(dim, c1, 2, ax, ex, 1, i1, -1);
const GeoDescriptor* ev[2] = {E0, E1};
/* (1) grounded claim — sits inside E0. */
float in[4] = {0.3f, -0.2f, 0, 0};
GeoGrounding g1;
int rc = engram_verify_grounding(in, dim, ev, 2, 1.0, 0.5, &g1);
ok("grounding returns 0", rc == 0);
printf("[grounding] IN score=%.4f grounded=%d best=%d dist=%.3f ortho=%.3f nearL2=%.3f\n",
g1.grounding, g1.grounded, g1.best, g1.best_distance, g1.best_ortho, g1.nearest_centroid_l2);
ok("planted-inside claim is GROUNDED", g1.grounded == 1);
ok("grounds to the nearest structure E0", g1.best == 0);
ok("grounded score high (>0.7)", g1.grounding > 0.7);
approx("off-model residual ~0 for in-distribution claim", g1.best_ortho, 0.0, 1e-4);
engram_verify_grounding_free(&g1);
/* (2) hallucinated claim — floats far along the unmodeled e2 axis. */
float out[4] = {0, 0, 50.0f, 0};
GeoGrounding g2;
engram_verify_grounding(out, dim, ev, 2, 1.0, 0.5, &g2);
printf("[grounding] OUT score=%.6f grounded=%d best=%d dist=%.3f ortho=%.3f nearL2=%.3f\n",
g2.grounding, g2.grounded, g2.best, g2.best_distance, g2.best_ortho, g2.nearest_centroid_l2);
ok("floating claim is FLAGGED (ungrounded)", g2.grounded == 0);
ok("floating claim scores near zero (<0.01)", g2.grounding < 0.01);
ok("off-model residual is large (the hallucination signal)", g2.best_ortho > 40.0);
ok("nearest real structure is far (L2>40)", g2.nearest_centroid_l2 > 40.0);
engram_verify_grounding_free(&g2);
/* (3) selection — a claim near E1 grounds to E1. */
float nearE1[4] = {9.8f, 0.1f, 0, 0};
GeoGrounding g3;
engram_verify_grounding(nearE1, dim, ev, 2, 1.0, 0.5, &g3);
printf("[grounding] E1 score=%.4f grounded=%d best=%d\n", g3.grounding, g3.grounded, g3.best);
ok("claim near E1 grounds to E1 (best=1)", g3.best == 1 && g3.grounded == 1);
engram_verify_grounding_free(&g3);
engram_geo_free(E0); engram_geo_free(E1);
}
/* ══════════════════ CONSISTENCY (a) — THE NEGATION-INVERSION CATCH ═══════ */
/* The motivating failure, geometrically. Polarity axis along e0:
* pole_pos = the AFFIRM region ("argued / fought") centroid (+5, …)
* pole_neg = the NEGATE region ("never fought / at peace") centroid (5, …)
* The grounded TRUTH (context) is the reassurance "you never fought" → sits on
* the NEGATE side (5). The bad translation CLAIM "you argued" lands on the
* AFFIRM side (+4). Opposite sides of the negation axis ⇒ INVERSION flagged —
* even though "you argued" is perfectly grammatical. This is the catch. */
{
int dim = 4;
double c_pos[4] = { 5, 0, 0, 0}; /* "argued / fought" */
double c_neg[4] = {-5, 0, 0, 0}; /* "never fought / at peace"*/
double c_truth[4] = {-5, 0, 0, 0}; /* context: the reassurance */
double ax[4] = {1,0,0,0}; double ex[1] = {1};
const char* ip[1]={"pos"},*in[1]={"neg"},*it[1]={"truth"};
GeoDescriptor* POS = mk(dim, c_pos, 1, ax, ex, 1, ip, -1);
GeoDescriptor* NEG = mk(dim, c_neg, 1, ax, ex, 1, in, -1);
GeoDescriptor* CTX = mk(dim, c_truth, 1, ax, ex, 1, it, -1);
/* the plausible LIE: "you argued" — grammatical, fluent, and INVERTED. */
float lie[4] = { 4, 0, 0, 0};
GeoConsistency cl;
int rc = engram_verify_consistency(lie, dim, CTX, POS, NEG, NULL,
1.0, 0.10, 0.5, 0.0, &cl);
ok("consistency returns 0", rc == 0);
printf("[consistency] LIE verdict=%d inverted=%d claim_side=%.3f ref_side=%.3f sep=%.3f consist=%.3f\n",
cl.verdict, cl.inverted, cl.polarity_claim, cl.polarity_reference, cl.polarity_separation, cl.consistency);
ok("NEGATION INVERSION caught (inverted=1)", cl.inverted == 1);
ok("verdict = POLARITY", cl.verdict == GEO_CONSIST_POLARITY);
ok("claim sits on the AFFIRM pole (+)", cl.polarity_claim > 0);
ok("truth sits on the NEGATE pole ()", cl.polarity_reference < 0);
ok("consistency collapses to 0 on inversion", cl.consistency < 1e-9);
/* the FAITHFUL translation: "you were at peace" — same pole as the truth. */
float ok_claim[4] = {-4, 0, 0, 0};
GeoConsistency cok;
engram_verify_consistency(ok_claim, dim, CTX, POS, NEG, NULL,
1.0, 0.10, 0.5, 0.0, &cok);
printf("[consistency] TRUE verdict=%d inverted=%d claim_side=%.3f consist=%.3f\n",
cok.verdict, cok.inverted, cok.polarity_claim, cok.consistency);
ok("faithful claim NOT flagged (inverted=0)", cok.inverted == 0);
ok("faithful claim verdict OK", cok.verdict == GEO_CONSIST_OK);
ok("faithful claim consistency = 1", cok.consistency > 0.999);
/* a NEUTRAL claim near the midpoint must NOT false-trigger. */
float neutral[4] = {0.1f, 0, 0, 0}; /* |side|=0.1 < deadzone 0.5 */
GeoConsistency cn;
engram_verify_consistency(neutral, dim, CTX, POS, NEG, NULL,
1.0, 0.10, 0.5, 0.0, &cn);
printf("[consistency] NEUT verdict=%d inverted=%d claim_side=%.3f consist=%.3f\n",
cn.verdict, cn.inverted, cn.polarity_claim, cn.consistency);
ok("neutral claim inside deadzone does NOT trigger inversion", cn.inverted == 0);
engram_geo_free(POS); engram_geo_free(NEG); engram_geo_free(CTX);
}
/* ══════════════════ CONSISTENCY (b) — GEOMETRIC contradiction ════════════ */
/* A claim that sits INSIDE a forbidden region it should be far from, and a claim
* that violates a max-distance constraint to its context, are both flagged. */
{
int dim = 4;
double c_ctx[4] = {0,0,0,0};
double c_forb[4] = {0,10,0,0}; /* forbidden region, offset along e1 */
double ax[8] = {0,1,0,0, 1,0,0,0}; double ex[2] = {1,1};
const char* ic[1]={"ctx"},*ifb[1]={"forb"};
GeoDescriptor* CTX = mk(dim, c_ctx, 2, ax, ex, 1, ic, -1);
GeoDescriptor* FORB = mk(dim, c_forb, 2, ax, ex, 1, ifb, -1);
/* claim sitting inside the forbidden region → geometric contradiction. */
float inside[4] = {0, 10.1f, 0, 0};
GeoConsistency cf;
engram_verify_consistency(inside, dim, CTX, NULL, NULL, FORB,
1.0, 0.10, 0.5, 0.0, &cf);
printf("[consistency] FORB verdict=%d geo_viol=%d forb_fit=%.4f consist=%.3f\n",
cf.verdict, cf.geo_violation, cf.forbidden_fit, cf.consistency);
ok("claim inside forbidden region FLAGGED", cf.geo_violation == 1);
ok("verdict = GEOMETRIC", cf.verdict == GEO_CONSIST_GEOMETRIC);
ok("forbidden fit is high (claim really is inside)", cf.forbidden_fit > 0.5);
/* claim well clear of the forbidden region → not flagged. */
float clear[4] = {0.2f, 0.1f, 0, 0};
GeoConsistency cc;
engram_verify_consistency(clear, dim, CTX, NULL, NULL, FORB,
1.0, 0.10, 0.5, 0.0, &cc);
printf("[consistency] CLR verdict=%d geo_viol=%d forb_fit=%.4f\n",
cc.verdict, cc.geo_violation, cc.forbidden_fit);
ok("claim clear of forbidden NOT flagged", cc.geo_violation == 0 && cc.verdict == GEO_CONSIST_OK);
/* max-distance constraint: claim too far from context (off-axis, no poles). */
float far[4] = {0, 8.0f, 0, 0};
GeoConsistency cd;
engram_verify_consistency(far, dim, CTX, NULL, NULL, NULL,
1.0, 0.10, 0.5, /*max_distance*/3.0, &cd);
printf("[consistency] DIST verdict=%d geo_viol=%d ctx_dist=%.3f\n",
cd.verdict, cd.geo_violation, cd.context_distance);
ok("claim beyond max_distance FLAGGED", cd.geo_violation == 1 && cd.verdict == GEO_CONSIST_GEOMETRIC);
approx("context distance measured correctly", cd.context_distance, 8.0, 1e-4);
engram_geo_free(CTX); engram_geo_free(FORB);
}
/* ══════════════════ COMBINED — grounded but INVERTED (the full plausible lie) */
/* The most dangerous output: fluent, GROUNDED in real vocabulary, yet polarity-
* inverted. Grounding alone passes it; only consistency catches the lie. This is
* exactly why the verifier needs BOTH checks. */
{
int dim = 4;
double c_pos[4] = { 5, 0, 0, 0}, c_neg[4] = {-5, 0, 0, 0};
double ax[4] = {1,0,0,0}; double ex[1] = {2};
const char* ip[1]={"pos"},*in[1]={"neg"};
GeoDescriptor* POS = mk(dim, c_pos, 1, ax, ex, 1, ip, -1);
GeoDescriptor* NEG = mk(dim, c_neg, 1, ax, ex, 1, in, -1);
const GeoDescriptor* ev[2] = {POS, NEG};
float lie[4] = {5, 0, 0, 0}; /* "argued" — sits dead-center in the affirm region */
GeoGrounding g;
engram_verify_grounding(lie, dim, ev, 2, 1.0, 0.5, &g);
GeoConsistency c;
engram_verify_consistency(lie, dim, NEG /*truth=never fought*/, POS, NEG, NULL,
1.0, 0.10, 0.5, 0.0, &c);
printf("[combined] grounded=%d (score=%.3f) inverted=%d verdict=%d\n",
g.grounded, g.grounding, c.inverted, c.verdict);
ok("plausible lie PASSES grounding (it is real vocabulary)", g.grounded == 1);
ok("plausible lie is CAUGHT by consistency (inverted)", c.inverted == 1);
ok("=> grounding alone is insufficient; consistency is the catch",
g.grounded == 1 && c.verdict == GEO_CONSIST_POLARITY);
engram_verify_grounding_free(&g);
engram_geo_free(POS); engram_geo_free(NEG);
}
printf("\n== %d checks, %d failures ==\n", checks, failures);
return failures ? 1 : 0;
}