/* ───────────────────────────────────────────────────────────────────────── * gep_proof.c — PROOF LEDGER for grounded edge-propagation (task #50). * * Self-contained. Builds three scenarios on an in-memory GepGraph that mirrors * the live EngramStore's flat node/edge arrays, runs the consolidation/dream * beat (gep_beat), and prints RAW grounding before/after for each: * * (A) STRENGTHEN — a conjecture + N independent grounded corroborators. * Grounding grows past threshold, GRADUATES conjecture→ * likely→grounded, then RELAXES when corroboration stops * (nothing is settled). * (B) DECAY — a grounded belief meets N independent CONTRADICTORY * corroborators. Grounding decays grounded→likely→conjecture. * (C) INDEPENDENCE GUARD — identical fan-in of N=5, weights, and standings. * C1: 5 DISTINCT independent corroborators → grounds. * C2: the SAME support echoed (5 mutually-linked / one node * repeated) → collapses to 1 independent → does NOT. * * Build: cc -std=c11 -O2 -o gep_proof gep_proof.c -lm * Run: ./gep_proof * ───────────────────────────────────────────────────────────────────────── */ #include #include #include "gep_core.h" #define T0 1786000000000LL /* fixed base time (ms) — deterministic */ #define BEAT_MS 60000LL /* 60s heartbeat cadence (awareness.el) */ /* Seed a node's grounding with a prior LTP event so it reads as already-grounded * (a member of the grounded core that gravity radiates from). mag→standing: * standing = GEP_BASE + mag (event at ~now). */ static void seed_grounded(GepNode* n, double mag, int64_t ts) { memset(&n->gr, 0, sizeof n->gr); gep_append(&n->gr, ts, +1, mag, 0); } /* Re-anchor every NON-belief node (the corroborators/refuters) as a freshly- * grounded member of the core AT time `now`. These nodes are, by definition, * sustained members of the grounded core — each has its OWN ongoing * corroboration — so their standing must be read as grounded at each beat, not * left to power-law-decay out of the core between beats. The belief-under-test * is NEVER re-anchored: its trajectory is driven only by the propagation. */ static void anchor_core(GepGraph* g, int64_t now, double mag) { for (int i = 0; i < g->n_nodes; i++) if (!g->nodes[i].is_belief) seed_grounded(&g->nodes[i], mag, now); } static void print_node(const char* tag, GepNode* n, int64_t now) { double s = gep_standing(&n->gr, now); printf(" %-14s standing=%.4f band=%-10s events=%d subthresh=%d\n", tag, s, gep_band(s), n->gr.filled, n->gr.subthreshold_hits); } /* Run one beat over a single belief node b and print the raw support decomposition. */ static void beat_and_report(GepGraph* g, int b, int64_t now, int beatno, const char* note) { anchor_core(g, now, 0.80); /* corroborators stay grounded at each beat */ double s_before = gep_standing(&g->nodes[b].gr, now); int r_before = gep_band_rank(s_before); double pos, neg; int np, nn, incident; int r = gep_propagate_node(g, b, now, &pos, &neg, &np, &nn, &incident); double s_after = gep_standing(&g->nodes[b].gr, now); int r_after = gep_band_rank(s_after); const char* action = (r > 0) ? "LTP (strengthen)" : (r < 0) ? "LTD (decay)" : (np || nn) ? "sub-threshold (no shift)" : (incident == 0) ? "isolated (no edges)" : "starved (no grounded neighbor)"; printf(" beat %d (t=+%llds) %s\n", beatno, (long long)((now - T0) / 1000), note ? note : ""); printf(" incident_edges=%d pos_mass=%.4f (n_indep=%d) neg_mass=%.4f (n_indep=%d)" " THETA=%.2f N_MIN=%d\n", incident, pos, np, neg, nn, (double)GEP_THETA, GEP_N_MIN); printf(" -> %-26s standing %.4f (%s) -> %.4f (%s)%s\n", action, s_before, gep_band(s_before), s_after, gep_band(s_after), (r_after > r_before) ? " [GRADUATED]" : (r_after < r_before) ? " [DEMOTED]" : ""); } /* ── Scenario A — STRENGTHEN + graduation + relaxation ───────────────────── */ static void scenario_A(void) { printf("\n=== SCENARIO A — STRENGTHEN: convergent independent corroboration ===\n"); /* nodes[0] = the conjecture (belief). nodes[1..8] = independent corroborators, * each already grounded, each tethered to the conjecture by a weak young * hebbian-associate edge (weight 0.15 = ENGRAM_HEBB_LINK_W0). The corroborators * are NOT linked to each other → fully independent. */ static GepNode nodes[9]; static GepEdge edges[8]; memset(nodes, 0, sizeof nodes); nodes[0].id = "conjecture"; nodes[0].is_belief = 1; /* bare: standing = BASE */ for (int i = 1; i <= 8; i++) { nodes[i].id = "corroborator"; seed_grounded(&nodes[i], 0.80, T0); /* standing ≈ 0.90 → grounded core */ } GepGraph g = { nodes, 9, edges, 0 }; printf(" seed: conjecture has NO grounding events; corroborators pre-grounded.\n"); print_node("conjecture", &nodes[0], T0); /* Beat 1: 3 independent corroborators have grounded up around the conjecture. */ g.n_edges = 0; for (int i = 1; i <= 3; i++) edges[g.n_edges++] = (GepEdge){ 0, i, 0.15, +1 }; beat_and_report(&g, 0, T0, 1, "3 independent grounded corroborators appear"); /* Beat 2: the neighborhood fills in — 5 independent corroborators now. */ g.n_edges = 0; for (int i = 1; i <= 5; i++) edges[g.n_edges++] = (GepEdge){ 0, i, 0.15, +1 }; beat_and_report(&g, 0, T0 + BEAT_MS, 2, "neighborhood grows to 5 corroborators"); /* Beat 3: support sustained at 5 (grounding refreshed). */ beat_and_report(&g, 0, T0 + 2 * BEAT_MS, 3, "support sustained (5)"); /* Beats 4-6: corroboration REMOVED (neighbors superseded / no longer ground). * No new events; the collection ages → standing relaxes. Nothing is settled. */ g.n_edges = 0; beat_and_report(&g, 0, T0 + 12 * BEAT_MS, 4, "corroboration withdrawn (+10min)"); beat_and_report(&g, 0, T0 + 60 * BEAT_MS, 5, "still withdrawn (+1h)"); beat_and_report(&g, 0, T0 + 240 * BEAT_MS, 6, "still withdrawn (+4h)"); printf(" RESULT: grounding grew automatically past threshold and graduated,\n" " then relaxed once the independent support stopped — living,\n" " not a latched flag.\n"); } /* ── Scenario B — DECAY via accreting contradiction ─────────────────────── */ static void scenario_B(void) { printf("\n=== SCENARIO B — DECAY: convergent independent CONTRADICTION ===\n"); static GepNode nodes[6]; static GepEdge edges[5]; memset(nodes, 0, sizeof nodes); nodes[0].id = "belief"; nodes[0].is_belief = 1; /* Seed the belief as already GROUNDED via a strong prior LTP event. */ seed_grounded(&nodes[0], 0.85, T0); for (int i = 1; i <= 5; i++) { nodes[i].id = "refuter"; seed_grounded(&nodes[i], 0.80, T0); /* grounded contradictors */ } GepGraph g = { nodes, 6, edges, 0 }; printf(" seed: belief pre-grounded by a strong prior LTP event.\n"); print_node("belief", &nodes[0], T0); /* Contradiction accretes over successive beats: 3 then 5 independent grounded * refuters (polarity -1). Each beat past threshold appends an LTD event. * Beat 1 runs at the seed instant so the trajectory starts from grounded. */ g.n_edges = 0; for (int i = 1; i <= 3; i++) edges[g.n_edges++] = (GepEdge){ 0, i, 0.20, -1 }; beat_and_report(&g, 0, T0, 1, "3 independent contradictions"); g.n_edges = 0; for (int i = 1; i <= 5; i++) edges[g.n_edges++] = (GepEdge){ 0, i, 0.20, -1 }; beat_and_report(&g, 0, T0 + BEAT_MS, 2, "contradiction broadens to 5"); beat_and_report(&g, 0, T0 + 2 * BEAT_MS, 3, "contradiction sustained (5)"); beat_and_report(&g, 0, T0 + 3 * BEAT_MS, 4, "contradiction sustained (5)"); printf(" RESULT: grounding decayed grounded->likely->conjecture under\n" " convergent independent contradiction. The door never shut\n" " on the belief; its history is retained (events keep growing).\n"); } /* ── Scenario C — INDEPENDENCE GUARD ─────────────────────────────────────── */ static void scenario_C(void) { printf("\n=== SCENARIO C — INDEPENDENCE GUARD (the load-bearing property) ===\n"); printf(" Both sub-cases: N=5 corroborators, edge weight 0.30, corroborator\n" " standing ~0.90. ONLY difference: whether the 5 are independent.\n"); /* C1 — 5 DISTINCT INDEPENDENT corroborators (no edges among them). */ { printf("\n -- C1: 5 DISTINCT independent corroborators --\n"); static GepNode nodes[6]; static GepEdge edges[5]; memset(nodes, 0, sizeof nodes); nodes[0].id = "conjecture"; nodes[0].is_belief = 1; for (int i = 1; i <= 5; i++) { nodes[i].id = "corr"; seed_grounded(&nodes[i], 0.80, T0); } for (int i = 1; i <= 5; i++) edges[i-1] = (GepEdge){ 0, i, 0.30, +1 }; GepGraph g = { nodes, 6, edges, 5 }; print_node("conjecture", &nodes[0], T0); beat_and_report(&g, 0, T0, 1, "5 independent corroborators (no inter-links)"); } /* C2 — the SAME support echoed: 5 corroborators that are all mutually linked * (a derivation clique — one source echoed through the chain). Same fan-in to * the conjecture, same weights, same standings. Union-find collapses them to * ONE independent component → below N_MIN → NO strengthening. */ { printf("\n -- C2: 5 corroborators, but mutually-linked (echo of ONE source) --\n"); static GepNode nodes[6]; static GepEdge edges[9]; /* 5 to conjecture + 4 chaining corr1..corr5 */ memset(nodes, 0, sizeof nodes); nodes[0].id = "conjecture"; nodes[0].is_belief = 1; for (int i = 1; i <= 5; i++) { nodes[i].id = "corr"; seed_grounded(&nodes[i], 0.80, T0); } int ne = 0; for (int i = 1; i <= 5; i++) edges[ne++] = (GepEdge){ 0, i, 0.30, +1 }; /* chain corr1-corr2-corr3-corr4-corr5: they are the same source echoed */ for (int i = 1; i <= 4; i++) edges[ne++] = (GepEdge){ i, i+1, 0.30, +1 }; GepGraph g = { nodes, 6, edges, ne }; print_node("conjecture", &nodes[0], T0); beat_and_report(&g, 0, T0, 1, "5 echoed (mutually-linked) corroborators"); } /* C3 — degenerate echo: literally ONE corroborator reached by 5 parallel edges. */ { printf("\n -- C3: ONE corroborator, reached by 5 parallel edges --\n"); static GepNode nodes[2]; static GepEdge edges[5]; memset(nodes, 0, sizeof nodes); nodes[0].id = "conjecture"; nodes[0].is_belief = 1; nodes[1].id = "corr"; seed_grounded(&nodes[1], 0.80, T0); for (int i = 0; i < 5; i++) edges[i] = (GepEdge){ 0, 1, 0.30, +1 }; GepGraph g = { nodes, 2, edges, 5 }; print_node("conjecture", &nodes[0], T0); beat_and_report(&g, 0, T0, 1, "same node, 5 parallel edges"); } printf("\n RESULT: identical raw fan-in (5) and mass inputs; C1 grounds because\n" " the corroboration is INDEPENDENT (5 components), C2/C3 do not\n" " because it collapses to ONE source. Circular self-reinforcement\n" " cannot manufacture grounding.\n"); } int main(void) { printf("GROUNDED EDGE-PROPAGATION — PROOF LEDGER (task #50)\n"); printf("constants: BASE=%.2f LIKELY_MIN=%.2f GROUNDED_MIN=%.2f " "N_MIN=%d THETA=%.2f D=%.1f\n", (double)GEP_BASE, (double)GEP_LIKELY_MIN, (double)GEP_GROUNDED_MIN, GEP_N_MIN, (double)GEP_THETA, (double)GEP_DECAY_D); scenario_A(); scenario_B(); scenario_C(); printf("\nDONE.\n"); return 0; }