#!/usr/bin/env bash # M3.5 PRE-FLIP GATE. Pure C harness (NOT elb/elc): links the real el_runtime.c # native engram builtins + engram_store.c and proves activation-time field # mutations (edge hebb, node activation_count, WM weight) persist through a # checkpoint and survive a reboot from neuron.egm with snapshot.json DELETED. # Writes ONLY under a throwaway /tmp dir with a throwaway HOME. set -u HERE="$(cd "$(dirname "$0")" && pwd)" RT="$HERE/../../lang/runtime/el_runtime.c" ST="$HERE/../../lang/runtime/engram_store.c" INC="$HERE/../../lang/runtime" WORK="$(mktemp -d /tmp/engram-m35-XXXXXX)" BIN="$WORK/m35" export HOME="$WORK/home"; mkdir -p "$HOME" # never touch real ~/.neuron export ENGRAM_WAL_SYNC=always unset ENGRAM_STORE fail=0 echo "== compiling harness (gcc: el_runtime.c + engram_store.c + test_m35_hebb_persist.c) ==" gcc -O1 -std=c11 -I "$INC" "$HERE/test_m35_hebb_persist.c" "$RT" "$ST" -lcurl -o "$BIN" 2>"$WORK/cc.log" if [ $? -ne 0 ]; then echo "COMPILE FAILED:"; cat "$WORK/cc.log"; rm -rf "$WORK"; exit 1; fi echo echo "== 0) flag-OFF: seed+activate+checkpoint must NOT touch the store ==" DOFF="$WORK/off"; mkdir -p "$DOFF" ( unset ENGRAM_STORE; "$BIN" offcheck "$DOFF" ) [ $? -ne 0 ] && { echo "FAIL: offcheck"; fail=1; } [ -e "$DOFF/neuron.egm" ] && { echo "FAIL: neuron.egm created while flag OFF"; fail=1; } \ || echo " ok: no neuron.egm created with flag OFF" echo echo "== 1) POSITIVE: ENGRAM_STORE=1 seed -> activate -> checkpoint(field-persist) -> close ==" DPOS="$WORK/pos"; mkdir -p "$DPOS" ENGRAM_STORE=1 "$BIN" pos_seed "$DPOS" || { echo "FAIL: pos_seed"; fail=1; } [ -e "$DPOS/neuron.egm" ] && echo " ok: neuron.egm created" || { echo "FAIL: neuron.egm missing"; fail=1; } echo echo "== 2) reboot from neuron.egm with snapshot.json DELETED (must never read JSON) ==" rm -f "$DPOS/snapshot.json" ENGRAM_STORE=1 "$BIN" pos_reboot "$DPOS" || { echo "FAIL: pos_reboot"; fail=1; } echo echo "== 3) NEGATIVE CONTROL: seed -> activate -> close WITHOUT the field-persist checkpoint ==" DNEG="$WORK/neg"; mkdir -p "$DNEG" ENGRAM_STORE=1 "$BIN" neg_seed "$DNEG" || { echo "FAIL: neg_seed"; fail=1; } rm -f "$DNEG/snapshot.json" ENGRAM_STORE=1 "$BIN" neg_reboot "$DNEG" || { echo "FAIL: neg_reboot"; fail=1; } echo echo "== 4) assertions (python over the JSON exports) ==" python3 - "$DPOS" "$DNEG" <<'PY' import json, sys, os WM_FLOOR = 0.05 HEBB_MIN = 1e-6 def load(d, name): with open(os.path.join(d, name)) as f: return json.load(f) def node_by_label(g, label): for n in g["nodes"]: if n.get("label") == label: return n return None def edge_between(g, a_id, b_id): for e in g["edges"]: if e.get("from_id") == a_id and e.get("to_id") == b_id: return e return None rc = 0 def check(cond, msg): global rc if cond: print(f" PASS: {msg}") else: print(f" FAIL: {msg}"); rc = 1 dpos, dneg = sys.argv[1], sys.argv[2] pre = load(dpos, "pre_reboot.json") rebt = load(dpos, "reboot.json") pa, pb = node_by_label(pre, "hebb-a"), node_by_label(pre, "hebb-b") ra = node_by_label(rebt, "hebb-a") assert pa and pb and ra, "target nodes missing" pe = edge_between(pre, pa["id"], pb["id"]) re = edge_between(rebt, pa["id"], pb["id"]) assert pe and re, "target edge missing" pre_hebb = pe.get("hebb", 0.0) rebt_hebb = re.get("hebb", 0.0) pre_ac = pa.get("activation_count", 0) rebt_ac = ra.get("activation_count", 0) pre_wm = pa.get("working_memory_weight", 0.0) rebt_wm = ra.get("working_memory_weight", 0.0) print(f" edge hebb-a->hebb-b : pre={pre_hebb!r} reboot={rebt_hebb!r}") print(f" node hebb-a act_cnt : pre={pre_ac!r} reboot={rebt_ac!r}") print(f" node hebb-a wm : pre={pre_wm!r} reboot={rebt_wm!r} (halved+floored expected)") # --- learning actually happened this run (else the test proves nothing) --- check(pre_hebb > HEBB_MIN, f"activation raised edge hebb above 0 (pre={pre_hebb})") check(pre_ac >= 1, f"activation reinforced node activation_count (pre={pre_ac})") check(pre_wm > 0.0, f"activation promoted node to working memory (pre_wm={pre_wm})") # --- the load-bearing survival assertions after a real delete-JSON reboot --- check(abs(rebt_hebb - pre_hebb) < 1e-12, f"edge hebb SURVIVED reboot unchanged ({rebt_hebb} == {pre_hebb})") check(rebt_ac == pre_ac, f"node activation_count SURVIVED reboot unchanged ({rebt_ac} == {pre_ac})") # --- WM weight: must equal the JSON path's boot transform exactly (halve+floor) --- expected_wm = pre_wm * 0.5 if expected_wm < WM_FLOOR: expected_wm = 0.0 check(abs(rebt_wm - expected_wm) < 1e-9, f"node WM weight SURVIVED with the SAME boot transform as JSON path " f"(reboot={rebt_wm} == halve+floor(pre)={expected_wm})") check(expected_wm > 0.0, f"WM survival is observable (halved weight stays above floor: {expected_wm} > {WM_FLOOR})") # --- NEGATIVE CONTROL: without the field-persist step the learning is LOST --- npre = load(dneg, "neg_pre.json") nrebt = load(dneg, "neg_reboot.json") na_pre = node_by_label(npre, "hebb-a") na_rebt = node_by_label(nrebt, "hebb-a") ne_pre = edge_between(npre, na_pre["id"], node_by_label(npre, "hebb-b")["id"]) ne_rebt = edge_between(nrebt, na_rebt["id"], node_by_label(nrebt, "hebb-b")["id"]) print(f" [neg] edge hebb : pre={ne_pre.get('hebb',0.0)!r} reboot={ne_rebt.get('hebb',0.0)!r}") print(f" [neg] node act_cnt : pre={na_pre.get('activation_count',0)!r} reboot={na_rebt.get('activation_count',0)!r}") check(ne_pre.get("hebb", 0.0) > HEBB_MIN, f"[neg] activation DID raise hebb in RAM (pre={ne_pre.get('hebb',0.0)})") check(ne_rebt.get("hebb", 0.0) == 0.0, "[neg] WITHOUT checkpoint field-persist, edge hebb is LOST on reboot (==0) — fix is load-bearing") check(na_rebt.get("activation_count", 0) == 0, "[neg] WITHOUT checkpoint field-persist, activation_count is LOST on reboot (==0)") sys.exit(rc) PY [ $? -ne 0 ] && fail=1 echo echo "== 5) ASan+UBSan build, exercise the full persist+reboot flow (leaks off — harness intentionally leaks el_strdup) ==" SANBIN="$WORK/m35.san" gcc -O1 -g -std=c11 -fsanitize=address,undefined -fno-sanitize-recover=undefined \ -I "$INC" "$HERE/test_m35_hebb_persist.c" "$RT" "$ST" -lcurl -o "$SANBIN" 2>"$WORK/san_cc.log" if [ $? -ne 0 ]; then echo " SAN COMPILE FAILED:"; tail -20 "$WORK/san_cc.log"; fail=1; else export ASAN_OPTIONS=detect_leaks=0 DSAN="$WORK/san"; mkdir -p "$DSAN" ENGRAM_STORE=1 "$SANBIN" pos_seed "$DSAN" >/dev/null 2>"$WORK/san_run.log" && \ { rm -f "$DSAN/snapshot.json"; ENGRAM_STORE=1 "$SANBIN" pos_reboot "$DSAN" >/dev/null 2>>"$WORK/san_run.log"; } if grep -qiE 'runtime error|AddressSanitizer|UndefinedBehavior|ERROR: ' "$WORK/san_run.log"; then echo " FAIL: sanitizer findings:"; grep -iE 'runtime error|Sanitizer|ERROR' "$WORK/san_run.log" | head; fail=1 else echo " ok: ASan+UBSan clean across pos_seed/checkpoint/reboot (field-persist, boot laundering)" fi fi echo if [ "$fail" -eq 0 ]; then echo "================ M3.5 HEBB-PERSIST GATE: PASS ================"; else echo "================ M3.5 HEBB-PERSIST GATE: FAIL ================"; fi rm -rf "$WORK" exit $fail