diff --git a/cmd/tapir/uploads_timeout_test.go b/cmd/tapir/uploads_timeout_test.go index f25d896..f39fc70 100644 --- a/cmd/tapir/uploads_timeout_test.go +++ b/cmd/tapir/uploads_timeout_test.go @@ -43,3 +43,36 @@ func TestBuildTranscriber_AWedgedPrimaryReachesTheFallbackBeforeTheJobDeadline(t require.NoError(t, err, "the wedged primary used the whole job and the fallback never ran") assert.Equal(t, "berget/kb-whisper", got.Endpoint) } + +func TestBuildTranscriber_AWedgedBaseEngineIsASoftFailureInTheEnsemble(t *testing.T) { + // The same deadline must guard the ensemble's BASE engine, not only the chain's primary + // (second adversarial review: the wiring was tested for the chain alone). + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + _ = r.ParseMultipartForm(1 << 20) + if r.FormValue("model") == "iguana/pianissimo" { + <-r.Context().Done() + return + } + w.Header().Set("Content-Type", "application/json") + _, _ = w.Write([]byte(`{"text":"hej","duration":1,"segments":[{"start":0,"end":1,"text":"hej"}]}`)) + })) + defer srv.Close() + cfg := uploadCfg(t, true) + cfg.GatewayURL = srv.URL + cfg.TranscribeModel = "iguana/kb-whisper" + cfg.ReconcileBaseModel = "iguana/pianissimo" + cfg.ReconcileModel = "iguana/gemma4-31b" + cfg.TranscribeEngineTimeout = 150 * time.Millisecond + wav := filepath.Join(t.TempDir(), "a.wav") + require.NoError(t, os.WriteFile(wav, []byte("RIFF....WAVEfmt "), 0o600)) + job, cancel := context.WithTimeout(context.Background(), 20*time.Second) + defer cancel() + + got, err := buildTranscriber(cfg).Transcribe(job, wav) + + require.NoError(t, err, "a wedged base engine must not use up the job") + assert.Equal(t, "hej", got.Text) + require.NotNil(t, got.Reconciliation) + assert.Equal(t, "single_engine", string(got.Reconciliation.Status)) + assert.Contains(t, got.Reconciliation.Reason, "timeout") +}