textmachine/backend/internal/config/promptlabel_pair_test.go

97 lines
4.2 KiB
Go

package config
import (
"os"
"path/filepath"
"strings"
"testing"
)
// promptlabel_pair_test.go: a pair labels its OWN prompts.
//
// ⛔ WHY THIS IS A MONEY PIN AND NOT TIDINESS. `prompt_version` folds into the snapshot, and a run config
// is pair-agnostic: one string in pipeline-c1.yaml labels the translator prompt of EVERY pair that config
// serves. Before this key, a pack that edited one pair's prompts had two ways to go and both were wrong —
// bump the shared label and re-snapshot (re-buy) the books of the pairs whose bytes never moved, or leave
// it and let one label stand over two different texts, which is exactly what the label ledger exists to
// catch. The third way is this file's subject.
// TestAPairLabelsItsOwnPromptsWithoutMovingAnother is the live proof on the SHIPPING files, not a fixture:
// the same run config, read for two pairs, must give the English prompts the pair's own label and leave
// the Chinese ones on the run config's.
func TestAPairLabelsItsOwnPromptsWithoutMovingAnother(t *testing.T) {
models, err := LoadModels(filepath.Join("..", "..", "configs", "models.yaml"))
if err != nil {
t.Fatalf("load models: %v", err)
}
cfg := filepath.Join("..", "..", "configs", "pipeline-c1.yaml")
labels := func(pair string) map[string]string {
t.Helper()
p, err := LoadPipeline(cfg, models, pair, nil)
if err != nil {
t.Fatalf("pipeline-c1 must load for %s: %v", pair, err)
}
out := map[string]string{}
for _, st := range p.Stages {
out[st.Name] = st.PromptVersion
}
return out
}
en, zh := labels("en-ru"), labels("zh-ru")
if len(en) == 0 || len(zh) == 0 {
t.Fatal("premise broken: the shipping config resolved no stages, so nothing below is about labels")
}
// The RUN CONFIG's own literal, read from the file rather than copied here — a copy would keep passing
// after somebody edited the config, which is the exact class of staleness this whole ledger is about.
raw, err := os.ReadFile(cfg)
if err != nil {
t.Fatal(err)
}
if !strings.Contains(string(raw), "prompt_version: "+zh["draft"]) {
t.Errorf("the zh-ru draft label %q is not the one pipeline-c1.yaml states — a pair that declares no label of its own must keep the run config's", zh["draft"])
}
if en["draft"] == zh["draft"] {
t.Errorf("both pairs' draft stages carry %q, so the en-ru prompt edit either did not happen or is riding the Chinese book's label — the pair layer's prompt_versions is what keeps them apart", en["draft"])
}
if en["edit"] == zh["edit"] {
t.Errorf("both pairs' edit stages carry %q; the same reasoning as the draft stage applies", en["edit"])
}
}
// TestAPairLabelKeyHasToNameAPromptFile pins the refusals. An empty label is the dangerous one: the stage
// check that demands a label has already passed by the time the pair layer is applied, so an empty value
// would REPLACE a stated label with nothing and the run would carry no comparability statement at all.
func TestAPairLabelKeyHasToNameAPromptFile(t *testing.T) {
dir := t.TempDir()
if err := os.MkdirAll(filepath.Join(dir, "pairs"), 0o755); err != nil {
t.Fatal(err)
}
write := func(body string) {
t.Helper()
if err := os.WriteFile(filepath.Join(dir, "pairs", "xx-yy.yaml"), []byte(body), 0o644); err != nil {
t.Fatal(err)
}
}
// PREMISE: a well-formed declaration loads and carries the label, or the refusals below would be
// indistinguishable from "this key does nothing at all".
write("pair: xx-yy\nprompt_versions:\n translator: v1-xx\n")
pc, err := LoadPair(dir, "xx-yy")
if err != nil || pc == nil {
t.Fatalf("a well-formed pair label must load: %v", err)
}
if pc.PromptVersions["translator"] != "v1-xx" {
t.Fatalf("the label must reach the pair config, got %+v", pc.PromptVersions)
}
for _, bad := range []struct{ name, body string }{
{"a path instead of a base name", "pair: xx-yy\nprompt_versions:\n ../translator: v1\n"},
{"a separator in the key", "pair: xx-yy\nprompt_versions:\n en-ru/translator: v1\n"},
{"an empty label", "pair: xx-yy\nprompt_versions:\n translator: \" \"\n"},
} {
t.Run(bad.name, func(t *testing.T) {
write(bad.body)
if _, err := LoadPair(dir, "xx-yy"); err == nil {
t.Error("must fail loud at load — a label nobody can resolve is not a smaller statement, it is a missing one")
}
})
}
}