package membank import ( "testing" "textmachine/backend/internal/store" ) // TestBaseEnrichedMemoryVersionSplit pins the WS1 §1в per-wave bank-version mechanism: the BASE // version (draft wave / draft-wave snapshot) excludes Source:"mined" rows, so adding a mined approved row // after the draft wave moves ONLY the ENRICHED version (edit wave / snapshot_W2) — keeping the draft wave checkpoints valid // («re-billed ONCE»). A broken split (base folding mined) would move draft-wave snapshot and re-bill the draft wave. func TestBaseEnrichedMemoryVersionSplit(t *testing.T) { seedRows := []store.GlossaryEntry{ {Src: "方源", Dst: "Фан Юань", Status: "approved", Source: "seed"}, {Src: "古月", Dst: "Гу Юэ", Status: "approved", Source: "ruby"}, } base0 := Materialize(seedRows, false) // Same rows PLUS a mined approved row (as a the draft wave.5 pass would add). enrichedRows := append([]store.GlossaryEntry{}, seedRows...) enrichedRows = append(enrichedRows, store.GlossaryEntry{Src: "蛊", Dst: "гу", Status: "approved", Source: "mined"}) bank1 := Materialize(enrichedRows, false) // 1) Base version is UNCHANGED by the mined addition (draft wave stays valid). if base0.BaseVersion() != bank1.BaseVersion() { t.Fatalf("base version moved on a mined-row addition — draft-wave snapshot would re-bill the draft wave:\n before %s\n after %s", base0.BaseVersion(), bank1.BaseVersion()) } // 2) Enriched version DID move (edit wave sees the new mined canon). if base0.Version() == bank1.Version() { t.Fatalf("enriched version did NOT move on a mined-row addition — the edit wave would miss the mined canon") } // 3) Base ≠ enriched even before any mined row (domain-separated), so a the draft wave job can never // accidentally content-address to a the edit wave checkpoint. if base0.BaseVersion() == base0.Version() { t.Fatalf("base and enriched versions collide over identical rows — they must be domain-separated") } } func TestMinedDeltaStaysBaseBankStable(t *testing.T) { // The mined delta (Source:"mined") must NOT move BaseVersion — the load-bearing «re-pay ONCE» // invariant (§1в): a bank-mining mined-row addition moves only the enriched version. The live mined-write // path (loadMinedDelta, mining.go) stamps Source:"mined"; this pins the invariant that stamp guarantees. // (Sibling of the Block-A TestBaseEnrichedMemoryVersionSplit.) seed := []store.GlossaryEntry{{Src: "方源", Dst: "Фан Юань", Status: "approved", Source: "seed"}} base0 := Materialize(seed, false) // An owner-promoted mined term (approved + dst, Source:"mined"), as the sign step emits it. mined := store.GlossaryEntry{Src: "龙公", Dst: "Лун Гун", Type: "name", Status: "approved", Source: "mined", SinceCh: 1, Confidence: 5} enriched := append(append([]store.GlossaryEntry{}, seed...), mined) bank1 := Materialize(enriched, false) if base0.BaseVersion() != bank1.BaseVersion() { t.Fatalf("base-bank-version moved on a Source:mined addition — draft-wave snapshot would re-bill the draft wave") } if base0.Version() == bank1.Version() { t.Fatalf("enriched version must move on a mined approved addition") } }