textmachine/backend/internal/membank/memory_wave_test.go

57 lines
3.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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")
}
}