package pipeline import ( "context" "strings" "testing" ) // allowshort_wire_test.go pins backlog 18 (D39.50 п.5) END TO END: an owner-SIGNED single-character term // (蛊, 转 — the two the polygon found unreachable) must reach the MODEL when the seed says allow_short, // and must stay unreachable without it. The bank-level override was already pinned (membank), but the // finding was «не доезжают ни одним каналом», which is a statement about the whole path — seed file → // materialization → selection → rendered injection → wire. The cold run's live signature relies on this // path, so it is verified at $0 first. const shortSeedAllowed = ` terms: - src: 蛊 dst: гу type: term status: approved allow_short: true decl: { invariant: true, forms: ["гу"] } ` const shortSeedPlain = ` terms: - src: 蛊 dst: гу type: term status: approved decl: { invariant: true, forms: ["гу"] } ` // shortSource names 蛊 twice — nothing else in the chunk can produce the dst, so the rendering's presence // on the wire is proof the key fired. const shortSource = "方源看着蛊,那是一只月光蛊。" func TestAllowShortReachesTheWire(t *testing.T) { for _, c := range []struct { name string seed string wantHit bool }{ {"allow_short signs the single-char key through", shortSeedAllowed, true}, {"without it the single-key ban still holds", shortSeedPlain, false}, } { t.Run(c.name, func(t *testing.T) { rec := &reqRec{} srv := newJSONProvider(rec, func(body string) (string, string) { if isEditBody(body) { return "Фан Юань смотрел на гу.", "stop" } return "Фан Юань смотрел на гу — лунный гу.", "stop" }) defer srv.Close() bookPath := setupProjectOpts(t, srv.URL, projectOpts{source: shortSource, glossarySeed: c.seed}) r := newRunner(t, bookPath) defer r.Close() if _, err := r.TranslateBook(context.Background()); err != nil { t.Fatal(err) } msgs := bodyMessages(t, translatorBody(t, rec)) injected := false for _, m := range msgs { if m.Role == "system" && strings.Contains(m.Content, "蛊 → гу") { injected = true } } if injected != c.wantHit { t.Fatalf("single-char key on the wire = %v, want %v; messages: %+v", injected, c.wantHit, msgs) } // The editor half of the same claim: a signed row is CANON for the bilingual editor, and the // section it lands in is the signed one (backlog 19 — provenance, not match confidence). for _, b := range rec.all() { if !isEditBody(b) { continue } em := bodyMessages(t, b) got := strings.Contains(em[1].Content, "蛊 → «гу»") if got != c.wantHit { t.Fatalf("editor canon carries the short term = %v, want %v: %q", got, c.wantHit, em[1].Content) } if c.wantHit && strings.Contains(em[1].Content, "⟨проверить⟩") { t.Fatalf("an owner-SIGNED row must not be rendered as unverified: %q", em[1].Content) } } }) } }