/* test_grounding_vector.c — deterministic tests for §7: the one decay model, the * consequence gate, and the stored/derived split. Links engram_cognition.c * directly; no server, no store, no network. See run_grounding_vector_tests.sh. * * NEGATIVE CONTROL (invariant §8.6). Every symbol exercised here — * cog_decay_factor, cog_grounding_significant, cog_significance_inherent, * CogGrounding, CogProvClass — is introduced by the change under test, so this * suite does not COMPILE against the pre-change source, let alone pass. The * runner documents the exact reproduction. */ #include "engram_cognition.h" #include #include #include #include static int fails = 0; static void ok(int cond, const char* what) { printf(" %-62s %s\n", what, cond ? "PASS" : "*** FAIL ***"); if (!cond) fails++; } /* The decay formula exactly as el_runtime.c carried it before the move, so the * refactor can be shown to be bit-identical rather than merely similar. */ static double old_engram_temporal_decay(long long age_ms, long long activation_count, double temporal_decay_rate) { if (age_ms <= 0) return 1.0; double lambda = (temporal_decay_rate > 0.0) ? temporal_decay_rate : 0.693147; double age_hours = (double)age_ms / 3600000.0; double t_half = 168.0 * (1.0 + log(1.0 + (double)activation_count)); double factor = exp(-lambda * age_hours / t_half); if (factor < 0.25) factor = 0.25; return factor; } static CogGrounding base(void) { CogGrounding g; memset(&g, 0, sizeof g); g.present = 1; g.factual = 0.60; g.relational = 0.60; g.factual_now = 0.60; g.relational_now = 0.60; g.associative = 0.1; g.polarity = 1.0; g.prov = COG_PROV_TOLD; g.fac_proj = 1.0; g.rel_proj = 1.0; g.cos_angle = 0.9; g.agreement = 1; g.ts = 1000; g.seq = 1; g.reinforcements = 3; return g; } int main(void) { const double F = 0.5, R = 0.5; printf("\n== 1. DECAY IS THE ONE MODEL, AND IT IS BIT-IDENTICAL TO WHAT IT REPLACED ==\n"); { long long ages[] = {0, 3600000LL, 86400000LL, 7*86400000LL, 30*86400000LL, 365*86400000LL}; int allsame = 1; for (int i = 0; i < 6; i++) for (int ac = 0; ac < 4; ac++) { long long acs[] = {0, 1, 10, 1000}; double a = cog_decay_factor(ages[i], (double)acs[ac], 0.0); double b = old_engram_temporal_decay(ages[i], acs[ac], 0.0); if (a != b) allsame = 0; } ok(allsame, "cog_decay_factor == the pre-move engram_temporal_decay (24 pts)"); ok(cog_decay_factor(0, 0, 0.0) == 1.0, "age 0 -> no decay"); } printf("\n DECAY OVER ELAPSED TIME (reinforcements = 0, default rate):\n"); printf(" %10s %10s\n", "elapsed", "decay"); { struct { const char* label; long long ms; } pts[] = { {"0", 0LL}, {"1 hour", 3600000LL}, {"1 day", 86400000LL}, {"3 days", 3LL*86400000LL}, {"7 days", 7LL*86400000LL}, {"14 days", 14LL*86400000LL}, {"30 days", 30LL*86400000LL}, {"90 days", 90LL*86400000LL}, }; double prev = 2.0; int monotone = 1; for (unsigned i = 0; i < sizeof pts / sizeof pts[0]; i++) { double d = cog_decay_factor(pts[i].ms, 0, 0.0); printf(" %10s %10.6f\n", pts[i].label, d); if (d > prev) monotone = 0; prev = d; } ok(monotone, "decay is monotone non-increasing in elapsed time"); ok(fabs(cog_decay_factor(7LL*86400000LL, 0, 0.0) - 0.5) < 1e-6, "7 days at zero reinforcements == exactly one half-life (0.5)"); ok(cog_decay_factor(7LL*86400000LL, 100, 0.0) > cog_decay_factor(7LL*86400000LL, 0, 0.0), "reinforcement slows ageing (Lindy term)"); ok(cog_decay_factor(3650LL*86400000LL, 0, 0.0) == 0.25, "floor is a preference not a cliff: bottoms out at 0.25"); } printf("\n== 2. CONSEQUENCE GATE: EVERY TRIGGER, AND NO EPSILON ANYWHERE ==\n"); { CogGrounding p = base(), n = base(); ok(cog_grounding_significant(&p, &n, F, R) == COG_SIG_NONE, "identical vectors -> NONE (a re-read must not consolidate)"); n = base(); n.factual = 0.9999; n.factual_now = 0.9999; ok(cog_grounding_significant(&p, &n, F, R) == COG_SIG_NONE, "factual 0.60 -> 0.9999 without crossing the floor -> NONE"); n = base(); n.relational = 0.5001; n.relational_now = 0.5001; ok(cog_grounding_significant(&p, &n, F, R) == COG_SIG_NONE, "relational 0.60 -> 0.5001, still above floor -> NONE"); n = base(); n.factual_now = 0.4999; ok(cog_grounding_significant(&p, &n, F, R) == COG_SIG_FACTUAL_FLOOR, "a 0.1001 drop that CROSSES the floor -> FACTUAL_FLOOR"); n = base(); n.relational_now = 0.4999; ok(cog_grounding_significant(&p, &n, F, R) == COG_SIG_RELATIONAL_FLOOR, "relational crossing its floor -> RELATIONAL_FLOOR"); n = base(); n.cos_angle = -0.05; n.agreement = -1; ok(cog_grounding_significant(&p, &n, F, R) == COG_SIG_AGREEMENT_FLIP, "agreement +1 -> -1 -> AGREEMENT_FLIP"); n = base(); n.fac_proj = -0.2; ok(cog_grounding_significant(&p, &n, F, R) == COG_SIG_DIRECTION_REVERSAL, "factual gradient reverses -> DIRECTION_REVERSAL"); n = base(); n.rel_proj = -0.2; ok(cog_grounding_significant(&p, &n, F, R) == COG_SIG_DIRECTION_REVERSAL, "relational gradient reverses -> DIRECTION_REVERSAL"); n = base(); n.polarity = -1.0; ok(cog_grounding_significant(&p, &n, F, R) == COG_SIG_POLARITY_FLIP, "support -> contradiction -> POLARITY_FLIP (inherent)"); n = base(); n.polarity = 0.0; ok(cog_grounding_significant(&p, &n, F, R) == COG_SIG_POLARITY_FLIP, "support -> ignorance (zero) -> POLARITY_FLIP: not the same state"); n = base(); n.prov = COG_PROV_OBSERVED; ok(cog_grounding_significant(&p, &n, F, R) == COG_SIG_PROVENANCE_CHANGE, "told -> observed -> PROVENANCE_CHANGE (inherent)"); CogGrounding fresh; memset(&fresh, 0, sizeof fresh); ok(cog_grounding_significant(&fresh, &n, F, R) == COG_SIG_FIRST_RECORD, "no prior version -> FIRST_RECORD"); } printf("\n== 3. INHERENT MOVES BYPASS THE SALIENCE GATE ==\n"); ok(cog_significance_inherent(COG_SIG_POLARITY_FLIP), "polarity flip is inherent"); ok(cog_significance_inherent(COG_SIG_PROVENANCE_CHANGE), "provenance change is inherent"); ok(cog_significance_inherent(COG_SIG_FIRST_RECORD), "first record is inherent"); ok(!cog_significance_inherent(COG_SIG_FACTUAL_FLOOR), "a floor crossing is NOT inherent"); ok(!cog_significance_inherent(COG_SIG_NONE), "NONE is not inherent"); printf("\n== 4. THE STORED/DERIVED SPLIT: DERIVED VALUES ARE NEVER SERIALIZED ==\n"); { CogGrounding g = base(); g.decay = 0.3333; g.factual_now = 0.1234; g.relational_now = 0.2345; g.associative_now = 0.4567; g.age_ms = 999999; g.stale = 1; char* m = cog_grounding_metadata("pre-existing=keepme", &g); ok(m != NULL, "serializer returns a document"); ok(m && strstr(m, "pre-existing=keepme"), "pre-existing edge metadata preserved verbatim"); ok(m && strstr(m, "GRD1"), "GRD1 magic present"); ok(m && !strstr(m, "0.3333"), "decay is NOT stored"); ok(m && !strstr(m, "0.1234"), "factual_now is NOT stored"); ok(m && !strstr(m, "0.2345"), "relational_now is NOT stored"); ok(m && !strstr(m, "0.4567"), "associative_now is NOT stored"); ok(m && !strstr(m, "999999"), "age is NOT stored"); ok(m && strstr(m, "told"), "provenance class IS stored"); ok(m && strstr(m, "0.6"), "the factual/relational dimensions ARE stored"); if (m) { printf("\n --- serialized GRD1 block ---\n%s -----------------------------\n", m); } free(m); } printf("\n%s (%d failure%s)\n\n", fails ? "SOME TESTS FAILED" : "ALL TESTS PASSED", fails, fails == 1 ? "" : "s"); return fails ? 1 : 0; }