133 lines
5.1 KiB
Go
133 lines
5.1 KiB
Go
package pipeline
|
|
|
|
// oracle_test.go: the cold-run-A oracle, IN THE TREE.
|
|
//
|
|
// ⛔ WHY IT IS HERE AND NOT IN A REPORT. The pack's own rule is that what must survive a restart lives in
|
|
// the repository; the comparison against the polygon's hand-built table (docs/experiments/24-door-to-file.md
|
|
// §7) existed only in a written report, so the single number the whole instrument was accepted on — «it
|
|
// reproduces the oracle» — could not be re-checked by anyone, ever. The TABLE is committed
|
|
// (testdata/oracle-run-a.json); the paid artifacts it is measured against are not, so the test skips when
|
|
// they are absent, exactly as the labelled-corpus harness next door does.
|
|
//
|
|
// ⚠ IT SKIPS UNDER A COPY-BASED WORKFLOW (tmmutate), because standdata.Root walks to the repo root and the
|
|
// books tree is not copied with the module. Named rather than implied: this pin is held by the battery and
|
|
// not by the mutation gate.
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"textmachine/backend/internal/lang"
|
|
"textmachine/backend/internal/membank"
|
|
"textmachine/backend/internal/standdata"
|
|
"textmachine/backend/internal/store"
|
|
)
|
|
|
|
var runADir = standdata.EnvOr("TM_RUN_A_DIR", standdata.StandFile("gu-zhenren", "door-to-file"))
|
|
|
|
type oracleTerm struct {
|
|
Src string `json:"src"`
|
|
BankDst string `json:"bank_dst"`
|
|
Population string `json:"population"`
|
|
Oracle string `json:"oracle"`
|
|
Instrument string `json:"instrument"`
|
|
Agrees bool `json:"agrees"`
|
|
}
|
|
|
|
type oracleDoc struct {
|
|
Agree int `json:"agree"`
|
|
Terms []oracleTerm `json:"terms"`
|
|
}
|
|
|
|
// frozenBank builds the bank as it stood at the mining stop of 04:39, from the projection that IS the
|
|
// frozen evidence. The stand database is a DIFFERENT revision — 12 rows were re-consolidated at 04:42 —
|
|
// so judging the oracle against it would be judging a different bank.
|
|
func frozenBank(t *testing.T) *membank.Bank {
|
|
t.Helper()
|
|
raw, err := os.ReadFile(filepath.Join(runADir, "bankstop-paid", "project.db.bank.json"))
|
|
if err != nil {
|
|
t.Skipf("run-A evidence absent (%v) — set TM_RUN_A_DIR to force", err)
|
|
}
|
|
var doc struct {
|
|
Proposed []struct{ Src, Dst string } `json:"proposed"`
|
|
}
|
|
if err := json.Unmarshal(raw, &doc); err != nil {
|
|
t.Fatalf("parse the frozen bank projection: %v", err)
|
|
}
|
|
rows := make([]store.GlossaryEntry, 0, len(doc.Proposed))
|
|
for _, p := range doc.Proposed {
|
|
rows = append(rows, store.GlossaryEntry{BookID: "runA", Src: p.Src, Dst: p.Dst, Status: "draft", Source: "seed"})
|
|
}
|
|
if len(rows) == 0 {
|
|
t.Fatalf("the frozen bank projection carries no proposals")
|
|
}
|
|
return membank.MaterializeBank(membank.BankInput{
|
|
Rows: rows, TargetStemmer: lang.NewTargetStemmer(lang.TargetChecksFor("ru")),
|
|
}, false)
|
|
}
|
|
|
|
// TestTheInstrumentAgainstTheColdRunOracle re-runs the comparison the pack was accepted on, over the same
|
|
// shipped units, and pins BOTH halves: which terms agree and which do not. A disagreement is not a failure
|
|
// here — three of them are properties this engine documents — but a disagreement that CHANGES is, because
|
|
// it means the instrument's verdict moved without anyone deciding that it should.
|
|
func TestTheInstrumentAgainstTheColdRunOracle(t *testing.T) {
|
|
raw, err := os.ReadFile(filepath.Join("testdata", "oracle-run-a.json"))
|
|
if err != nil {
|
|
t.Fatalf("the oracle table is part of the repository: %v", err)
|
|
}
|
|
var want oracleDoc
|
|
if err := json.Unmarshal(raw, &want); err != nil {
|
|
t.Fatalf("parse the oracle table: %v", err)
|
|
}
|
|
bank := frozenBank(t) // skips when the paid artifacts are absent
|
|
|
|
pairs, err := os.ReadFile(filepath.Join(runADir, "pairs.json"))
|
|
if err != nil {
|
|
t.Skipf("run-A shipped units absent (%v) — set TM_RUN_A_DIR to force", err)
|
|
}
|
|
var exp struct {
|
|
Chunks []struct {
|
|
Chapter int `json:"chapter"`
|
|
Source string `json:"source"`
|
|
FinalText string `json:"final_text"`
|
|
} `json:"chunks"`
|
|
}
|
|
if err := json.Unmarshal(pairs, &exp); err != nil {
|
|
t.Fatalf("parse the shipped units: %v", err)
|
|
}
|
|
c := newConsistencyScan(bank)
|
|
for _, u := range exp.Chunks {
|
|
c.add(u.Chapter, u.Source, u.FinalText)
|
|
}
|
|
// The denominator is the bank the scan actually ran over, so the partition below is about the same rows.
|
|
rows := make([]store.GlossaryEntry, 0)
|
|
for _, term := range want.Terms {
|
|
rows = append(rows, store.GlossaryEntry{BookID: "runA", Src: term.Src, Dst: term.BankDst, Status: "draft"})
|
|
}
|
|
got := c.finish(rows)
|
|
|
|
verdict := map[string]string{}
|
|
for _, term := range got.Terms {
|
|
verdict[term.Src] = term.Verdict
|
|
}
|
|
agree := 0
|
|
for _, term := range want.Terms {
|
|
v := verdict[term.Src]
|
|
if v == "" {
|
|
v = "covered"
|
|
}
|
|
if v != term.Instrument {
|
|
t.Errorf("%s: the instrument now says %q where the table records %q (the oracle says %q) — a verdict moved without anyone deciding it should",
|
|
term.Src, v, term.Instrument, term.Oracle)
|
|
}
|
|
if v == term.Oracle {
|
|
agree++
|
|
}
|
|
}
|
|
if agree != want.Agree {
|
|
t.Errorf("agreement with the hand-built oracle is %d of %d; the table records %d", agree, len(want.Terms), want.Agree)
|
|
}
|
|
t.Logf("oracle agreement: %d of %d terms (the table's recorded disagreements are documented properties, not defects)", agree, len(want.Terms))
|
|
}
|