File size: 3,284 Bytes
a3f913d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
// Run 2 Plan §B3, gate item 2: retell_count must survive checkpoint save/restore.
// NOT covered by --checkpoint_gate's hash proof -- world_hash() (main.cpp) hashes
// mem_id/importance/type/source_depth/text but never retell_count, so a bug here would
// pass that gate silently. This test touches the SQLite round-trip directly instead.
// No LlamaBridge needed (WorldState only holds a pointer to it), so this links against
// db.cpp + sqlite3 only -- no llama.cpp, fast to build and run.
#include "infra/db.h"
#include "engine/world.h"
#include <cassert>
#include <cstdio>
#include <cstdlib>

using namespace tbv;

int main() {
    const char* dbpath = "/tmp/tbv_retell_count_gate.db";
    std::remove(dbpath);

    WorldState w;
    w.init(12345);
    w.run_id = "retell_gate";

    // Hand-place a few memories with distinct retell_count values across different
    // villagers, including edge values (0, and a large one near uint16_t range) --
    // exercises the actual bind/column int path in db.cpp, not just "happens to be 0".
    auto make_mem = [](uint32_t mem_id, uint16_t retell_count, const std::string& text) {
        MemoryEntry m;
        m.mem_id = mem_id;
        m.tick = 5;
        m.actor_id = 0;
        m.importance = 1000;
        m.type = MemType::EXPERIENCE;
        m.source_depth = 0;
        m.origin_mem_id = mem_id;
        m.text = text;
        m.retell_count = retell_count;
        return m;
    };
    w.stores[0].add(make_mem(1, 0, "never retold"), 5);
    w.stores[0].add(make_mem(2, 5, "retold five times"), 5);
    w.stores[3].add(make_mem(3, 65535, "max uint16 retell count"), 5);
    w.stores[99].add(make_mem(4, 150, "villager 99, one RETELL_PENALTY worth"), 5);

    Database db(dbpath);
    db.init_schema();
    db.save_checkpoint(w);

    WorldState restored;
    restored.init(999); // different seed on purpose -- restore must fully overwrite, not merge
    restored.run_id = "retell_gate"; // load_checkpoint keys on this; init() doesn't set it
    bool loaded = db.load_checkpoint(restored);
    if (!loaded) { std::fprintf(stderr, "FAIL: load_checkpoint found no row\n"); return 1; }

    auto find = [](const CognitiveStore& store, uint32_t mem_id) -> const MemoryEntry* {
        for (const auto& m : store.all()) if (m.mem_id == mem_id) return &m;
        return nullptr;
    };

    struct Check { uint32_t villager; uint32_t mem_id; uint16_t expected; };
    Check checks[] = {
        {0, 1, 0}, {0, 2, 5}, {3, 3, 65535}, {99, 4, 150},
    };
    bool all_ok = true;
    for (const auto& c : checks) {
        const MemoryEntry* m = find(restored.stores[c.villager], c.mem_id);
        if (!m) {
            std::fprintf(stderr, "FAIL: villager %u mem_id %u missing after restore\n", c.villager, c.mem_id);
            all_ok = false;
            continue;
        }
        bool ok = (m->retell_count == c.expected);
        std::printf("villager %u mem_id %u: retell_count=%u expected=%u %s\n",
                    c.villager, c.mem_id, m->retell_count, c.expected, ok ? "OK" : "FAIL");
        all_ok = all_ok && ok;
    }

    std::printf(all_ok ? "PASS: retell_count round-trips through checkpoint save/restore\n"
                        : "FAIL: retell_count did not round-trip\n");
    return all_ok ? 0 : 1;
}