feat: upload audio, get a private Swedish transcript, discuss it (#33, ADR-033) #39

Merged
mathias merged 299 commits from feat/33-audio-upload-transcript into main 2026-10-03 14:13:37 +00:00
Showing only changes of commit 0b7bf08c95 - Show all commits
+20 -6
View File
@@ -84,7 +84,12 @@ func TestReconcile_BaseAndUnsureVerdictsKeepTheBaseButOnlyUnsureIsFlagged(t *tes
assert.Equal(t, "Totalt 1015 kronor till SEB.", keptBase.Text) assert.Equal(t, "Totalt 1015 kronor till SEB.", keptBase.Text)
assert.Zero(t, keptBase.Reconciliation.Unsure) assert.Zero(t, keptBase.Reconciliation.Unsure)
assert.Empty(t, keptBase.Reconciliation.Contested, "a confident 'the base is right' is not a spot worth the reader's time") require.Len(t, keptBase.Reconciliation.Contested, 2,
"every judged spot is stored, kept ones too: without them the reconciler cannot be compared with either engine alone (ADR-035)")
for _, c := range keptBase.Reconciliation.Contested {
assert.Equal(t, "base", c.Used)
assert.False(t, c.Unsure, "a confident 'the base is right' is stored but is not an uncertain spot")
}
assert.Equal(t, "Totalt 1015 kronor till SEB.", unsure.Text, "unsure keeps the base") assert.Equal(t, "Totalt 1015 kronor till SEB.", unsure.Text, "unsure keeps the base")
assert.Equal(t, 2, unsure.Reconciliation.Unsure) assert.Equal(t, 2, unsure.Reconciliation.Unsure)
require.Len(t, unsure.Reconciliation.Contested, 2) require.Len(t, unsure.Reconciliation.Contested, 2)
@@ -224,14 +229,16 @@ func TestReconcile_ACancelledJobIsAnErrorNotASkippedReconciliation(t *testing.T)
assert.ErrorIs(t, err, context.Canceled, "a shutdown must not be recorded as 'the model was unavailable'") assert.ErrorIs(t, err, context.Canceled, "a shutdown must not be recorded as 'the model was unavailable'")
} }
func TestReconcile_KeepsTheBaseSegmentsDurationAndNamesTheEngines(t *testing.T) { func TestReconcile_KeepsTheBaseTimingAndDurationAndNamesTheEngines(t *testing.T) {
base := tr("a x b") base := tr("a x b")
base.Segments = []domain.Segment{{Start: 0, End: 4, Text: "a x b"}} base.Segments = []domain.Segment{{Start: 0, End: 4, Text: "a x b"}}
base.AudioSeconds = 3821.5 base.AudioSeconds = 3821.5
out := merge(t, base, tr("a y b"), always(reconcile.VerdictAlt)) out := merge(t, base, tr("a y b"), always(reconcile.VerdictAlt))
assert.Equal(t, base.Segments, out.Segments, "the timed segments are the base engine's, untouched") require.Len(t, out.Segments, 1)
assert.InDelta(t, 0.0, out.Segments[0].Start, 1e-9, "timing is the base engine's")
assert.InDelta(t, 4.0, out.Segments[0].End, 1e-9)
assert.InDelta(t, 3821.5, out.AudioSeconds, 1e-9) assert.InDelta(t, 3821.5, out.AudioSeconds, 1e-9)
assert.Equal(t, "iguana/pianissimo", out.Reconciliation.Base) assert.Equal(t, "iguana/pianissimo", out.Reconciliation.Base)
assert.Equal(t, "iguana/kb-whisper", out.Reconciliation.Alt) assert.Equal(t, "iguana/kb-whisper", out.Reconciliation.Alt)
@@ -264,18 +271,25 @@ func TestReconcile_WithNoSegmentsASpotIsPlacedProportionally(t *testing.T) {
assert.InDelta(t, 90.0, out.Reconciliation.Contested[0].Seconds, 1e-9, "token 9 of 10 in 100 s") assert.InDelta(t, 90.0, out.Reconciliation.Contested[0].Seconds, 1e-9, "token 9 of 10 in 100 s")
} }
func TestReconcile_ContestedSpotsAreCappedButTheCountsAreExact(t *testing.T) { func TestReconcile_JudgedSpotsAreCappedButTheCountsAreExact(t *testing.T) {
a, b := make([]string, 0, 600), make([]string, 0, 600) a, b := make([]string, 0, 600), make([]string, 0, 600)
for i := 0; i < 300; i++ { for i := 0; i < 300; i++ {
a = append(a, fmt.Sprintf("w%d", i), "same", "same2") a = append(a, fmt.Sprintf("w%d", i), "same", "same2")
b = append(b, fmt.Sprintf("v%d", i), "same", "same2") b = append(b, fmt.Sprintf("v%d", i), "same", "same2")
} }
capped := opts
capped.MaxContested = 50
out := merge(t, tr(strings.Join(a, " ")), tr(strings.Join(b, " ")), always(reconcile.VerdictUnsure)) out, err := reconcile.Reconcile(context.Background(), tr(strings.Join(a, " ")), tr(strings.Join(b, " ")), always(reconcile.VerdictUnsure), capped)
require.NoError(t, err)
assert.Equal(t, 300, out.Reconciliation.Unsure) assert.Equal(t, 300, out.Reconciliation.Unsure)
assert.Equal(t, 300, out.Reconciliation.Disputes) assert.Equal(t, 300, out.Reconciliation.Disputes)
assert.Len(t, out.Reconciliation.Contested, reconcile.MaxContested, "the stored list is bounded; the counts are not") assert.Len(t, out.Reconciliation.Contested, 50, "the stored list is bounded; the counts are not")
}
func TestReconcile_TheDefaultCapIsAFewThousandSoAWholeMeetingIsKept(t *testing.T) {
assert.Equal(t, 2000, reconcile.MaxContested, "a 90-minute recording has a few hundred judged spots; the cap is a guard, not a budget")
} }
func TestReconcile_AVerdictReturnedAlongsideAnErrorIsIgnored(t *testing.T) { func TestReconcile_AVerdictReturnedAlongsideAnErrorIsIgnored(t *testing.T) {