feat(uploads): an auto-language job is planned without the engines it never runs (#61)

PlanFor(lang) on the Ensemble and a LanguagePlanner the worker prefers: the page lists
the other engine (and the fallback if configured), not the base engine, the comparison and
the decisions as coming. Found by the PR #62 review.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-04 22:41:21 +02:00
co-authored by Claude Sonnet 5.5
parent 0828f0debf
commit e0c53f8719
4 changed files with 96 additions and 10 deletions
+18 -8
View File
@@ -32,14 +32,24 @@ func NewEnsemble(base, alt, fallback Backend, adj reconcile.Adjudicator, opts re
return &Ensemble{base: base, alt: alt, fallback: fallback, adj: adj, opts: opts}
}
// Plan implements uploads.Planner: the phases this ensemble reports, so the page can
// show them before they run. The fallback is a phase only when one is configured.
func (e *Ensemble) Plan() []progress.Planned {
plan := []progress.Planned{
{Key: "engine_a", Label: "Transcribing with " + e.base.Name()},
{Key: "engine_b", Label: "Transcribing with " + e.alt.Name()},
{Key: "compare", Label: "Comparing the two transcripts"},
{Key: "decide", Label: "Deciding the differences"},
// Plan implements uploads.Planner: the phases of a Swedish job, the two-engine one. The
// fallback is a phase only when one is configured.
func (e *Ensemble) Plan() []progress.Planned { return e.PlanFor(domain.LangSwedish) }
// PlanFor implements uploads.LanguagePlanner. A recording that is not Swedish never runs the
// base engine, the comparison or the decisions (transcribeOther), so the page lists only
// what can run: the other engine, then the fallback if one is configured.
func (e *Ensemble) PlanFor(lang domain.Language) []progress.Planned {
var plan []progress.Planned
if lang == domain.LangSwedish || lang == "" {
plan = []progress.Planned{
{Key: "engine_a", Label: "Transcribing with " + e.base.Name()},
{Key: "engine_b", Label: "Transcribing with " + e.alt.Name()},
{Key: "compare", Label: "Comparing the two transcripts"},
{Key: "decide", Label: "Deciding the differences"},
}
} else {
plan = []progress.Planned{{Key: "engine_b", Label: "Transcribing with " + e.alt.Name()}}
}
if e.fallback != nil {
plan = append(plan, progress.Planned{Key: "fallback", Label: "Cloud fallback (" + e.fallback.Name() + ")"})
@@ -160,3 +160,22 @@ func TestEnsembleProgress_TheReconcileCountsAreNotedForTheOperator(t *testing.T)
assert.Equal(t, 0, n["unsure"])
assert.Equal(t, 0, n["errors"])
}
// An auto-language upload never runs the base engine, the comparison or the decisions, so the
// page must not list them as coming (tapir#61, PR #62 review).
func TestEnsemblePlanFor_AnAutoLanguageListsOnlyThePhasesThatCanRun(t *testing.T) {
with := newEnsemble("a", "a", nil, nil, true, &verdictAdj{}).e
without := newEnsemble("a", "a", nil, nil, false, &verdictAdj{}).e
keys := func(p []progress.Planned) []string {
var k []string
for _, s := range p {
k = append(k, s.Key)
}
return k
}
assert.Equal(t, []string{"engine_b", "fallback"}, keys(with.PlanFor(domain.LangAuto)))
assert.Equal(t, []string{"engine_b"}, keys(without.PlanFor(domain.LangAuto)), "no fallback configured: none promised")
assert.Equal(t, with.Plan(), with.PlanFor(domain.LangSwedish), "Swedish is the plan it always was")
assert.Contains(t, with.PlanFor(domain.LangAuto)[0].Label, "iguana/kb-whisper")
}