Files
el/engram/spec/grounded-edge-propagation/LEDGER.md
T
bigmerge 5f3ddb8b8d
El SDK CI - dev / build-and-test (pull_request) Failing after 14m31s
Add grounded edge-propagation spec (task #50): core algorithm, proof harness, gated integration patches
LTP/LTD-style belief grounding propagated along graph edges, with
union-find independence-guarded corroboration. Package: core C algorithm
(gep_core.h), a self-contained deterministic proof harness with recorded
output, staged runtime integration, and gated .el patches for the beat
hook and HTTP route.

Per the author's own LEDGER.md: built + proven on a clone, GATED pending
the engine/HNSW cutover — not wired into the live beat or routes.
Preserved here as a spec/reference artifact, not a request to merge into
the live path.
2026-08-15 14:26:06 -05:00

9.2 KiB
Raw Blame History

Task #50 — Edge-aware, dream-coupled consolidation with GROUNDED EDGE-PROPAGATION

Status: built + proven on a clone; GATED, not promoted. The main loop sequences live promotion after the engine/HNSW cutover settles. Date: 2026-08-15 · Worktree: agent-a6577c8211c332c5b (isolated).

Grounding mechanism designed with Will (memory 9e09a59f, refining 1a861007). This is the HOW for #50.


(a) How grounded edge-propagation integrates into the dream/consolidation cycle

The beat already exists. neuron/awareness.el runs a heartbeat (~every beat_ms); each beat calls hebb_consolidate() — which drains the self-formed Hebbian associations out of the fast in-process store and writes them, over the threshold ENGRAM_HEBB_LINK_MIN, into the durable engram (:8742) — and then emit_heartbeat().

Grounded edge-propagation slots into the same beat, immediately after consolidation (awareness.el line 12861288):

hebb_consolidate()      // lay down the tethers (edges) that cleared threshold
ground_propagate()      // <-- NEW: grade beliefs ALONG those tethers
emit_heartbeat()        // report gep_* gauges beside hebb_*

This ordering is the point. Consolidation lays down the wiring; propagation grades the beliefs along it, in the same breath. Memory 69b8babe: memory-consolidation and staying-yourself are one physics — forming a memory and grading a belief are the same gravity run in two passes of one beat.

The propagation runs inside the engram as the native engram_ground_propagate() over the durable flat node/edge arrays (the store the consolidated edges just landed in). The soul invokes it over HTTP (POST /api/ground/propagate) and folds the returned gep_* telemetry into the heartbeat stream next to hebb_cands / hebb_mass / hebb_edges.

Bounded by construction (per the live-graph reality — 70.7% of nodes isolated, connected core ~28%, hub first-hop fan-out in the thousands):

  • 1-hop only. No BFS spreading activation — a belief is graded from its DIRECT grounded neighbors, so there is no per-hop breadth explosion.
  • Beam-capped at GEP_MAX_CORR = 256 corroborators per belief.
  • Salience-ordered, GEP_BELIEFS_PER_BEAT = 512 beliefs per beat; the rest next beat. Work per beat is O(beliefs × degree), hard-bounded.
  • Isolated / starved beliefs are counted and surfaced (gep_isolated, gep_starved) as an interoceptive sparse-region signal for the edge-formation / embedding pass (#20). #50 CONSUMES edges; it does not form them. A belief with no grounded neighbor has nothing to tether to — correct per the anti-delusion gravity law (0b15017c), not a gap.

(b) The implementation

Represented faithfully to the spec — grounding is a Hebbian-weighted collection over time, never a scalar.

  • Grounding = an append-only event ring on the node (GepGrounding), structurally parallel to the ACT-R base-level access ring already in EngramNode (access_ts[K]). Each event is {ts, sign±, mag, corroborator signature}. Append-only, supersede-not-delete; events aged out of the ring are counted (older_count), never faked away.
  • Standing is DERIVED, recency-weighted, never storedstanding = clamp(GEP_BASE + Σ_events sign·mag·age^(-D), 0, 1), exactly the ACT-R base-level shape ln Σ t^-d (ENGRAM_BLL_D = 0.5) but sign-carrying so LTD subtracts. Memory 1a861007: the collection is primary, the standing is its emergent aggregate. Mirrored onto confidence each beat so downstream reads (verifier #43, realizer calibration 0041d917) never speak above the grounding.
  • Update = LTP/LTD with a threshold. Per belief, gather corroborators along incident edges, weighted by edge.weight (the Hebbian weight) × the neighbor's own standing. Anti-delusion gravity: only neighbors already ≥ GEP_LIKELY_MIN may corroborate — grounding flows FROM the grounded core.
  • Convergent INDEPENDENT corroboration is the driver. Independence is enforced by union-find over the corroborator set: two corroborators are the same independent source if they are the same node, reached by multiple edges, or linked to each other (an echo chain / shared derivation). Support is summed per independent component (max-magnitude member), and the threshold gate requires BOTH a mass floor (pos ≥ GEP_THETA) AND an independence-count floor (n_independent ≥ GEP_N_MIN). The count gate is the guard against one node echoed N times.
  • Sub-threshold is transient. Support present but below threshold → subthreshold_hits++, no durable event, no lasting shift (Will's exact spec).
  • Graduation / decay. Cross up → LTP event appended → standing climbs conjecture → likely → grounded. Contradiction past threshold → LTD → grounded → likely → conjecture. Nothing latches; withdraw support and the collection ages and relaxes (271f1163, nothing is settled).

Files

File Role
gep_core.h The mechanism. Pure C, libm only (own-the-core). Single source of truth: GepGrounding, gep_standing, gep_append, union-find independence, gep_propagate_node, gep_beat.
gep_proof.c Self-contained proof harness — builds the three scenarios, prints raw before/after.
engram_ground_propagate.staged.c GATED runtime native. Wires the SAME gep_core.h primitives to the live EngramStore (adj cache, flat arrays). Splice plan + relation→polarity + belief gate. Compiles only when spliced (verified: every runtime symbol it references — engram_adj_rebuild, adj_from_len, engram_find_node_index, ENGRAM_LAYER_SAFETY, istr_contains, … — exists in the release runtime).
awareness.beat.patch.el GATED beat hook — ground_propagate() + the insert between hebb_consolidate() and emit_heartbeat().
server.route.patch.el GATED route — POST /api/ground/propagate.

Constants

BASE=0.10 LIKELY_MIN=0.34 GROUNDED_MIN=0.66 N_MIN=3 THETA=0.30 D=0.5 (N_MIN parameterizes Will's "13 adjacent things" — the count threshold is a knob; 3 here for a crisp proof.)


(c) PROOF LEDGER — raw grounding before/after

Deterministic. Build cc -std=c11 -O2 -o gep_proof gep_proof.c -lm, run ./gep_proof (full transcript in PROOF_OUTPUT.txt).

(a) STRENGTHEN — convergent independent corroboration graduates a conjecture

beat event pos_mass (n_indep) action standing before → after band
1 3 independent grounded corroborators 0.4050 (3) LTP 0.1000 → 0.4842 conjecture → likely
2 neighborhood grows to 5 0.6750 (5) LTP 0.1496 → 0.7379 conjecture → grounded
3 support sustained (5) 0.6750 (5) LTP 0.2110 → 0.7993 grounded (sustained)
4 corroboration withdrawn (+10min) 0.0000 (0) isolated 0.1612 → 0.1612 relaxing
5 still withdrawn (+1h) isolated 0.1263 relaxing
6 still withdrawn (+4h) isolated 0.1130 → conjecture

Grounding grew on its own past threshold and graduated conjecture → likely → grounded, then relaxed once independent support stopped. Living, not a latched flag.

(b) DECAY — convergent independent contradiction erodes a grounded belief

beat event neg_mass (n_indep) action standing before → after band
seed (prior LTP) 0.9500 grounded
1 3 independent contradictions 0.5400 (3) LTD 0.9500 → 0.4570 grounded → likely
2 contradiction broadens to 5 0.9000 (5) LTD 0.1461 → 0.0000 conjecture ⬇
34 contradiction sustained (5) 0.9000 (5) LTD 0.0000 conjecture

Grounding decayed grounded → likely → conjecture under accreting independent contradiction. The door never shut — history is retained (the event ring keeps growing), the belief stays falsifiable in both directions.

(c) INDEPENDENCE GUARD — the load-bearing property

Identical fan-in (N=5), identical edge weight (0.30), identical corroborator standing (~0.90). The only difference is whether the five are independent.

sub-case topology pos_mass n_indep action standing 0.1000 →
C1 5 DISTINCT, no inter-links 1.3500 5 LTP 0.9741 (grounded)
C2 5 mutually-linked (echo of one source) 0.2700 1 sub-threshold 0.1000 (unchanged)
C3 1 node reached by 5 parallel edges 0.2700 1 sub-threshold 0.1000 (unchanged)

Same raw fan-in, opposite outcome. Union-find collapses the echoes to a single independent component; the count gate (n_indep ≥ N_MIN) then refuses them. Circular self-reinforcement cannot manufacture grounding — a conjecture can only be grounded by evidence that is genuinely independent of itself.


RAILS honored: isolated worktree; built/proven on a clone; the live soul (:8742 / :7770) untouched; no fight with the cutover (built against current release source; staged native rebases cleanly onto it); no new libraries (libm only); identity keystones untouched. Not promoted — gated artifact + ledger for the main loop to sequence.