GVOVKH5R27K75VXGSZCP3X62FGNCSMDVFEKLR3LFXERFB54CHTUQC t.Run("should parse basic WAV metadata", func(t *testing.T) {path := createTestWAVFile(t, tmpDir, "test_basic.wav", struct {duration float64sampleRate intchannels intbitsPerSample intcomment stringartist string}{duration: 60.0,sampleRate: 44100,channels: 2,bitsPerSample: 16,comment: "",artist: "",})
path := createTestWAVFile(t, tmpDir, "test_basic.wav", struct {duration float64sampleRate intchannels intbitsPerSample intcomment stringartist string}{duration: 60.0,sampleRate: 44100,channels: 2,bitsPerSample: 16,comment: "",artist: "",})
if metadata.SampleRate != 44100 {t.Errorf("SampleRate incorrect: got %d, want 44100", metadata.SampleRate)}if metadata.Channels != 2 {t.Errorf("Channels incorrect: got %d, want 2", metadata.Channels)}
if metadata.SampleRate != 44100 {t.Errorf("SampleRate incorrect: got %d, want 44100", metadata.SampleRate)}if metadata.Channels != 2 {t.Errorf("Channels incorrect: got %d, want 2", metadata.Channels)}if metadata.BitsPerSample != 16 {t.Errorf("BitsPerSample incorrect: got %d, want 16", metadata.BitsPerSample)}if metadata.Duration < 59.9 || metadata.Duration > 60.1 {t.Errorf("Duration incorrect: got %f, want ~60.0", metadata.Duration)}}
// Duration should be approximately 60 seconds (allow small rounding error)if metadata.Duration < 59.9 || metadata.Duration > 60.1 {t.Errorf("Duration incorrect: got %f, want ~60.0", metadata.Duration)}
expectedComment := "Recorded at 21:00:00 24/02/2025 (UTC+13) by AudioMoth 248AB50153AB0549"path := createTestWAVFile(t, tmpDir, "test_comment.wav", struct {duration float64sampleRate intchannels intbitsPerSample intcomment stringartist string}{duration: 10.0,sampleRate: 48000,channels: 1,bitsPerSample: 16,comment: expectedComment,artist: "",
t.Run("should extract comment metadata", func(t *testing.T) {expectedComment := "Recorded at 21:00:00 24/02/2025 (UTC+13) by AudioMoth 248AB50153AB0549"path := createTestWAVFile(t, tmpDir, "test_comment.wav", struct {duration float64sampleRate intchannels intbitsPerSample intcomment stringartist string}{duration: 10.0,sampleRate: 48000,channels: 1,bitsPerSample: 16,comment: expectedComment,artist: "",})
metadata, err := ParseWAVHeader(path)if err != nil {t.Fatalf("Failed to parse WAV header: %v", err)}
t.Run("should extract artist metadata", func(t *testing.T) {expectedArtist := "AudioMoth"path := createTestWAVFile(t, tmpDir, "test_artist.wav", struct {duration float64sampleRate intchannels intbitsPerSample intcomment stringartist string}{duration: 5.0,sampleRate: 48000,channels: 1,bitsPerSample: 16,comment: "",artist: expectedArtist,})metadata, err := ParseWAVHeader(path)if err != nil {t.Fatalf("Failed to parse WAV header: %v", err)}if metadata.Artist != expectedArtist {t.Errorf("Artist incorrect: got %q, want %q", metadata.Artist, expectedArtist)}
expectedArtist := "AudioMoth"path := createTestWAVFile(t, tmpDir, "test_artist.wav", struct {duration float64sampleRate intchannels intbitsPerSample intcomment stringartist string}{duration: 5.0,sampleRate: 48000,channels: 1,bitsPerSample: 16,comment: "",artist: expectedArtist,
t.Run("should extract both comment and artist", func(t *testing.T) {expectedComment := "Test recording comment"expectedArtist := "Test Artist"path := createTestWAVFile(t, tmpDir, "test_both.wav", struct {duration float64sampleRate intchannels intbitsPerSample intcomment stringartist string}{duration: 15.0,sampleRate: 44100,channels: 2,bitsPerSample: 16,comment: expectedComment,artist: expectedArtist,})
metadata, err := ParseWAVHeader(path)if err != nil {t.Fatalf("Failed to parse WAV header: %v", err)}
if metadata.Artist != expectedArtist {t.Errorf("Artist incorrect: got %q, want %q", metadata.Artist, expectedArtist)}
expectedComment := "Test recording comment"expectedArtist := "Test Artist"path := createTestWAVFile(t, tmpDir, "test_both.wav", struct {duration float64sampleRate intchannels intbitsPerSample intcomment stringartist string}{duration: 15.0,sampleRate: 44100,channels: 2,bitsPerSample: 16,comment: expectedComment,artist: expectedArtist,
t.Run("should handle different sample rates", func(t *testing.T) {testCases := []struct {sampleRate int}{{8000},{16000},{22050},{44100},{48000},{96000},}
metadata, err := ParseWAVHeader(path)if err != nil {t.Fatalf("Failed to parse WAV header: %v", err)}
for _, tc := range testCases {t.Run("", func(t *testing.T) {path := createTestWAVFile(t, tmpDir, "test_sr.wav", struct {duration float64sampleRate intchannels intbitsPerSample intcomment stringartist string}{duration: 1.0,sampleRate: tc.sampleRate,channels: 1,bitsPerSample: 16,comment: "",artist: "",})
if metadata.Comment != expectedComment {t.Errorf("Comment incorrect: got %q, want %q", metadata.Comment, expectedComment)}if metadata.Artist != expectedArtist {t.Errorf("Artist incorrect: got %q, want %q", metadata.Artist, expectedArtist)}}
if metadata.SampleRate != tc.sampleRate {t.Errorf("SampleRate incorrect: got %d, want %d", metadata.SampleRate, tc.sampleRate)}
testCases := []int{8000, 16000, 22050, 44100, 48000, 96000}for _, sr := range testCases {t.Run(fmt.Sprintf("%dHz", sr), func(t *testing.T) {path := createTestWAVFile(t, tmpDir, fmt.Sprintf("test_sr_%d.wav", sr), struct {duration float64sampleRate intchannels intbitsPerSample intcomment stringartist string}{duration: 1.0,sampleRate: sr,channels: 1,bitsPerSample: 16,comment: "",artist: "",
for _, tc := range testCases {t.Run("", func(t *testing.T) {path := createTestWAVFile(t, tmpDir, "test_ch.wav", struct {duration float64sampleRate intchannels intbitsPerSample intcomment stringartist string}{duration: 1.0,sampleRate: 44100,channels: tc.channels,bitsPerSample: 16,comment: "",artist: "",})
if metadata.SampleRate != sr {t.Errorf("SampleRate incorrect: got %d, want %d", metadata.SampleRate, sr)}})}}
if metadata.Channels != tc.channels {t.Errorf("Channels incorrect: got %d, want %d", metadata.Channels, tc.channels)}
testCases := []int{1, 2}for _, ch := range testCases {t.Run(fmt.Sprintf("%dch", ch), func(t *testing.T) {path := createTestWAVFile(t, tmpDir, fmt.Sprintf("test_ch_%d.wav", ch), struct {duration float64sampleRate intchannels intbitsPerSample intcomment stringartist string}{duration: 1.0,sampleRate: 44100,channels: ch,bitsPerSample: 16,comment: "",artist: "",
for _, tc := range testCases {t.Run("", func(t *testing.T) {path := createTestWAVFile(t, tmpDir, "test_bits.wav", struct {duration float64sampleRate intchannels intbitsPerSample intcomment stringartist string}{duration: 1.0,sampleRate: 44100,channels: 1,bitsPerSample: tc.bitsPerSample,comment: "",artist: "",})
if metadata.Channels != ch {t.Errorf("Channels incorrect: got %d, want %d", metadata.Channels, ch)}})}}
if metadata.BitsPerSample != tc.bitsPerSample {t.Errorf("BitsPerSample incorrect: got %d, want %d", metadata.BitsPerSample, tc.bitsPerSample)}
testCases := []int{8, 16, 24, 32}for _, bits := range testCases {t.Run(fmt.Sprintf("%dbit", bits), func(t *testing.T) {path := createTestWAVFile(t, tmpDir, fmt.Sprintf("test_bits_%d.wav", bits), struct {duration float64sampleRate intchannels intbitsPerSample intcomment stringartist string}{duration: 1.0,sampleRate: 44100,channels: 1,bitsPerSample: bits,comment: "",artist: "",
t.Run("should handle very short durations", func(t *testing.T) {path := createTestWAVFile(t, tmpDir, "test_short.wav", struct {duration float64sampleRate intchannels intbitsPerSample intcomment stringartist string}{duration: 0.1, // 100mssampleRate: 44100,channels: 1,bitsPerSample: 16,comment: "",artist: "",
metadata, err := ParseWAVHeader(path)if err != nil {t.Fatalf("Failed to parse WAV header: %v", err)}if metadata.BitsPerSample != bits {t.Errorf("BitsPerSample incorrect: got %d, want %d", metadata.BitsPerSample, bits)}
if metadata.Duration < 0.09 || metadata.Duration > 0.11 {t.Errorf("Duration incorrect: got %f, want ~0.1", metadata.Duration)}
path := createTestWAVFile(t, tmpDir, "test_short.wav", struct {duration float64sampleRate intchannels intbitsPerSample intcomment stringartist string}{duration: 0.1, // 100mssampleRate: 44100,channels: 1,bitsPerSample: 16,comment: "",artist: "",
t.Run("should handle long durations", func(t *testing.T) {path := createTestWAVFile(t, tmpDir, "test_long.wav", struct {duration float64sampleRate intchannels intbitsPerSample intcomment stringartist string}{duration: 600.0, // 10 minutessampleRate: 44100,channels: 1,bitsPerSample: 16,comment: "",artist: "",})
metadata, err := ParseWAVHeader(path)if err != nil {t.Fatalf("Failed to parse WAV header: %v", err)}
t.Run("should return error for non-existent file", func(t *testing.T) {_, err := ParseWAVHeader("/nonexistent/file.wav")if err == nil {t.Error("Expected error for non-existent file")}
path := createTestWAVFile(t, tmpDir, "test_long.wav", struct {duration float64sampleRate intchannels intbitsPerSample intcomment stringartist string}{duration: 600.0, // 10 minutessampleRate: 44100,channels: 1,bitsPerSample: 16,comment: "",artist: "",
t.Run("should return error for non-WAV file", func(t *testing.T) {// Create a non-WAV filepath := filepath.Join(tmpDir, "not_a_wav.txt")if err := os.WriteFile(path, []byte("This is not a WAV file"), 0644); err != nil {t.Fatalf("Failed to create test file: %v", err)}
metadata, err := ParseWAVHeader(path)if err != nil {t.Fatalf("Failed to parse WAV header: %v", err)}
t.Run("should return error for truncated file", func(t *testing.T) {// Create a file that's too small to be valid WAVpath := filepath.Join(tmpDir, "truncated.wav")if err := os.WriteFile(path, []byte("RIFF"), 0644); err != nil {t.Fatalf("Failed to create test file: %v", err)}
func TestParseWAVHeader_NonExistentFile(t *testing.T) {_, err := ParseWAVHeader("/nonexistent/file.wav")if err == nil {t.Error("Expected error for non-existent file")}}
t.Run("should handle empty metadata strings", func(t *testing.T) {path := createTestWAVFile(t, tmpDir, "test_empty.wav", struct {duration float64sampleRate intchannels intbitsPerSample intcomment stringartist string}{duration: 10.0,sampleRate: 44100,channels: 1,bitsPerSample: 16,comment: "",artist: "",})
path := filepath.Join(tmpDir, "not_a_wav.txt")if err := os.WriteFile(path, []byte("This is not a WAV file"), 0644); err != nil {t.Fatalf("Failed to create test file: %v", err)}_, err := ParseWAVHeader(path)if err == nil {t.Error("Expected error for non-WAV file")}}func TestParseWAVHeader_TruncatedFile(t *testing.T) {tmpDir := t.TempDir()path := filepath.Join(tmpDir, "truncated.wav")if err := os.WriteFile(path, []byte("RIFF"), 0644); err != nil {t.Fatalf("Failed to create test file: %v", err)}
if metadata.Artist != "" {t.Errorf("Artist should be empty, got %q", metadata.Artist)}
path := createTestWAVFile(t, tmpDir, "test_empty.wav", struct {duration float64sampleRate intchannels intbitsPerSample intcomment stringartist string}{duration: 10.0,sampleRate: 44100,channels: 1,bitsPerSample: 16,comment: "",artist: "",
t.Run("should handle long comment strings", func(t *testing.T) {longComment := "Recorded at 21:00:00 24/02/2025 (UTC+13) by AudioMoth 248AB50153AB0549 at medium gain while battery was 4.3V and temperature was 15.8C. This is a very long comment with additional information about the recording session."
metadata, err := ParseWAVHeader(path)if err != nil {t.Fatalf("Failed to parse WAV header: %v", err)}
path := createTestWAVFile(t, tmpDir, "test_long_comment.wav", struct {duration float64sampleRate intchannels intbitsPerSample intcomment stringartist string}{duration: 10.0,sampleRate: 44100,channels: 1,bitsPerSample: 16,comment: longComment,artist: "",})
if metadata.Comment != "" {t.Errorf("Comment should be empty, got %q", metadata.Comment)}if metadata.Artist != "" {t.Errorf("Artist should be empty, got %q", metadata.Artist)}}func TestParseWAVHeader_LongCommentString(t *testing.T) {tmpDir := t.TempDir()
metadata, err := ParseWAVHeader(path)if err != nil {t.Fatalf("Failed to parse WAV header: %v", err)}
longComment := "Recorded at 21:00:00 24/02/2025 (UTC+13) by AudioMoth 248AB50153AB0549 at medium gain while battery was 4.3V and temperature was 15.8C. This is a very long comment with additional information about the recording session."
if metadata.Comment != longComment {t.Errorf("Comment incorrect: got %q, want %q", metadata.Comment, longComment)}
path := createTestWAVFile(t, tmpDir, "test_long_comment.wav", struct {duration float64sampleRate intchannels intbitsPerSample intcomment stringartist string}{duration: 10.0,sampleRate: 44100,channels: 1,bitsPerSample: 16,comment: longComment,artist: "",
t.Run("should extract file modification time", func(t *testing.T) {path := createTestWAVFile(t, tmpDir, "test_modtime.wav", struct {duration float64sampleRate intchannels intbitsPerSample intcomment stringartist string}{duration: 5.0,sampleRate: 44100,channels: 1,bitsPerSample: 16,comment: "",artist: "",})
metadata, err := ParseWAVHeader(path)if err != nil {t.Fatalf("Failed to parse WAV header: %v", err)}if metadata.Comment != longComment {t.Errorf("Comment incorrect: got %q, want %q", metadata.Comment, longComment)}}func TestParseWAVHeader_FileModTime(t *testing.T) {tmpDir := t.TempDir()
// Get expected mod timeinfo, err := os.Stat(path)if err != nil {t.Fatalf("Failed to stat file: %v", err)}expectedModTime := info.ModTime()
path := createTestWAVFile(t, tmpDir, "test_modtime.wav", struct {duration float64sampleRate intchannels intbitsPerSample intcomment stringartist string}{duration: 5.0,sampleRate: 44100,channels: 1,bitsPerSample: 16,comment: "",artist: "",})
// Allow 1 second tolerance for filesystem granularitydiff := metadata.FileModTime.Sub(expectedModTime)if diff < -1*time.Second || diff > 1*time.Second {t.Errorf("FileModTime incorrect: got %v, want %v (diff: %v)",metadata.FileModTime, expectedModTime, diff)}
metadata, err := ParseWAVHeader(path)if err != nil {t.Fatalf("Failed to parse WAV header: %v", err)}
// Ensure FileModTime is not zeroif metadata.FileModTime.IsZero() {t.Error("FileModTime should not be zero")}})
// Allow 1 second tolerance for filesystem granularitydiff := metadata.FileModTime.Sub(expectedModTime)if diff < -1*time.Second || diff > 1*time.Second {t.Errorf("FileModTime incorrect: got %v, want %v (diff: %v)",metadata.FileModTime, expectedModTime, diff)}if metadata.FileModTime.IsZero() {t.Error("FileModTime should not be zero")}
primary := m.awaitingSecondaryForm.awaitingSecondaryFor = ""// Esc cancels wait mode; species stays labeled without calltype,// segment does not advance.if key.Code == tea.KeyEscape || key.Code == tea.KeyEsc {return m, nil
if handled, model, cmd := m.handleSecondaryWait(msg); handled {return model, cmd
s := msg.String()if len(s) == 1 {if callType, ok := m.state.Config.SecondaryBindings[primary][s]; ok {if m.state.Player != nil {m.state.Player.Stop()}m.state.ApplyCallTypeOnly(callType)if err := m.state.Save(); err != nil {m.err = err.Error()}if !m.state.NextSegment() {m.quitting = truereturn m, tea.Quit}return m, m.segmentChangeCmd()
if handled, model, cmd := m.handleSpecialKey(msg); handled {return model, cmd}return m.handleSwitchKey(msg)}// handleSecondaryWait handles keypresses while awaiting a secondary calltype key.// Returns (true, model, cmd) if the key was consumed; (false, model, cmd) to fall through.func (m Model) handleSecondaryWait(msg tea.KeyPressMsg) (bool, tea.Model, tea.Cmd) {primary := m.awaitingSecondaryForm.awaitingSecondaryFor = ""if msg.Key().Code == tea.KeyEscape || msg.Key().Code == tea.KeyEsc {return true, m, nil}s := msg.String()if len(s) == 1 {if callType, ok := m.state.Config.SecondaryBindings[primary][s]; ok {m.stopPlayer()m.state.ApplyCallTypeOnly(callType)if err := m.state.Save(); err != nil {m.err = err.Error()
// Handle Enter key (main or numpad, check code to catch modifiers)
// handleSpecialKey handles single-key-code bindings (Enter, Esc, Space, Ctrl+S).// Returns (true, model, cmd) if the key was consumed.func (m Model) handleSpecialKey(msg tea.KeyPressMsg) (bool, tea.Model, tea.Cmd) {key := msg.Key()
// Shift+letter: if the lowercase primary has secondary bindings,// label species-only and enter wait mode. Otherwise map to the// lowercase equivalent and dispatch as a normal primary keypress.if key.Mod&tea.ModShift != 0 {lower := strings.ToLower(s)if lower != s {if m.state.HasSecondary(lower) {if result := m.state.ParseKeyBuffer(lower); result != nil {if m.state.Player != nil {m.state.Player.Stop()}m.state.ApplyBinding(&tools.BindingResult{Species: result.Species})if err := m.state.Save(); err != nil {m.err = err.Error()}m.awaitingSecondaryFor = lowerreturn m, nil}
// handleBindingKey handles single-character key bindings (species/calltype shortcuts).func (m Model) handleBindingKey(msg tea.KeyPressMsg) (tea.Model, tea.Cmd) {s := msg.String()if len(s) != 1 {return m, nil}k := skey := msg.Key()// Shift+letter: if the lowercase primary has secondary bindings,// label species-only and enter wait mode. Otherwise map to the// lowercase equivalent and dispatch as a normal primary keypress.if key.Mod&tea.ModShift != 0 {lower := strings.ToLower(s)if lower != s {if m.state.HasSecondary(lower) {if result := m.state.ParseKeyBuffer(lower); result != nil {m.stopPlayer()m.state.ApplyBinding(&tools.BindingResult{Species: result.Species})if err := m.state.Save(); err != nil {m.err = err.Error()
if result := m.state.ParseKeyBuffer(k); result != nil {if m.state.Player != nil {m.state.Player.Stop()}m.state.ApplyBinding(result)if err := m.state.Save(); err != nil {m.err = err.Error()}if !m.state.NextSegment() {m.quitting = truereturn m, tea.Quit}return m, m.segmentChangeCmd()}
if result := m.state.ParseKeyBuffer(k); result != nil {m.stopPlayer()m.state.ApplyBinding(result)if err := m.state.Save(); err != nil {m.err = err.Error()
return m, nil
return m.advanceOrQuit()}return m, nil}// stopPlayer stops the audio player if it exists.func (m Model) stopPlayer() {if m.state.Player != nil {m.state.Player.Stop()}}// advanceOrQuit advances to the next segment, or quits if none remain.func (m Model) advanceOrQuit() (tea.Model, tea.Cmd) {if !m.state.NextSegment() {m.quitting = truereturn m, tea.Quit
func TestFix(t *testing.T) {cmd := exec.Command("go", "fix", "./...")
func TestGolangciLint(t *testing.T) {cmd := exec.Command("golangci-lint", "run", "./...")cmd.Dir = "."out, err := cmd.CombinedOutput()if err != nil {t.Errorf("golangci-lint failed:\n%s", out)}}func TestDeadcode(t *testing.T) {cmd := exec.Command("deadcode", "./...")
switch v := param.(type) {case time.Time:return v.Format(time.RFC3339Nano)case *time.Time:if v == nil {
// Handle pointer types via reflection: nil → null, else dereference and recurse.// This covers all *T cases (including *time.Time) without explicit type switches.rv := reflect.ValueOf(param)if rv.Kind() == reflect.Pointer {if rv.IsNil() {
return vcase *string:if v == nil {return nil}return *vcase int:return vcase *int:if v == nil {return nil}return *vcase int8:return vcase *int8:if v == nil {return nil}return *vcase int16:return vcase *int16:if v == nil {return nil}return *vcase int32:return vcase *int32:if v == nil {return nil}return *vcase int64:return vcase *int64:if v == nil {return nil}return *vcase uint:return vcase *uint:if v == nil {return nil}return *vcase uint8:return vcase *uint8:if v == nil {return nil}return *vcase uint16:return vcase *uint16:if v == nil {return nil}return *vcase uint32:return vcase *uint32:if v == nil {return nil}return *vcase uint64:return vcase *uint64:if v == nil {return nil}return *vcase float32:return vcase *float32:if v == nil {return nil}return *vcase float64:
// Handle pointer types via reflection (e.g., *GainLevel, *CustomType)rv := reflect.ValueOf(param)if rv.Kind() == reflect.Pointer {if rv.IsNil() {return nil}// Dereference and recursively marshal the underlying valuereturn marshalParam(rv.Elem().Interface())}// For other types, try to convert to string via fmt.Sprintf
// clipArgParser holds state for parsing CLI arguments incrementally.type clipArgParser struct {args []stringi int}// nextValue returns the next argument after the current flag, or exits with an error.func (p *clipArgParser) nextValue(flag string) string {if p.i+1 >= len(p.args) {fmt.Fprintf(os.Stderr, "Error: %s requires a value\n", flag)os.Exit(1)}v := p.args[p.i+1]p.i += 2return v}// nextInt parses the next argument as an integer, or exits with an error.func (p *clipArgParser) nextInt(flag string) int {s := p.nextValue(flag)v, err := strconv.Atoi(s)if err != nil {fmt.Fprintf(os.Stderr, "Error: %s must be an integer\n", flag)os.Exit(1)}return v}
// nextFloat parses the next argument as a float64, or exits with an error.func (p *clipArgParser) nextFloat(flag string) float64 {s := p.nextValue(flag)v, err := strconv.ParseFloat(s, 64)if err != nil {fmt.Fprintf(os.Stderr, "Error: %s must be a number\n", flag)os.Exit(1)}return v}
if i+1 >= len(args) {fmt.Fprintf(os.Stderr, "Error: --certainty requires a value\n")os.Exit(1)}v, err := strconv.Atoi(args[i+1])if err != nil {fmt.Fprintf(os.Stderr, "Error: --certainty must be an integer\n")os.Exit(1)}
v := p.nextInt(arg)
if i+1 >= len(args) {fmt.Fprintf(os.Stderr, "Error: --size requires a value\n")os.Exit(1)}v, err := strconv.Atoi(args[i+1])if err != nil {fmt.Fprintf(os.Stderr, "Error: --size must be an integer\n")os.Exit(1)}size = vi += 2
size = p.nextInt(arg)
if i+1 >= len(args) {fmt.Fprintf(os.Stderr, "Error: --lat requires a value\n")os.Exit(1)}v, err := strconv.ParseFloat(args[i+1], 64)if err != nil {fmt.Fprintf(os.Stderr, "Error: --lat must be a number\n")os.Exit(1)}lat = v
lat = p.nextFloat(arg)
if i+1 >= len(args) {fmt.Fprintf(os.Stderr, "Error: --lng requires a value\n")os.Exit(1)}v, err := strconv.ParseFloat(args[i+1], 64)if err != nil {fmt.Fprintf(os.Stderr, "Error: --lng must be a number\n")os.Exit(1)}lng = v
lng = p.nextFloat(arg)
## [2026-05-04] Reduce cyclomatic complexity of marshalParam, RunCallsClip, TestParseWAVHeaderThree functions exceeded gocyclo threshold of 40:1. **`marshalParam` (db/tx_logger.go) — 50 → ~8**: Replaced 25 repetitive pointer-typecases (`*int`, `*string`, `*float64`, etc.) with the existing reflection-based pointerhandling that was already in the `default` branch. All value types kept as a singlemulti-type switch case.2. **`RunCallsClip` (cmd/calls_clip.go) — 50 → 35**: Extracted `clipArgParser` structwith `nextValue()`, `nextInt()`, `nextFloat()` helpers that encapsulate the"check bounds + advance + error" pattern repeated 13 times in the arg loop.3. **`TestParseWAVHeader` (utils/wav_metadata_test.go) — 44 → ~5 each**: Split themonolithic test with 14 `t.Run` sub-tests into 14 top-level `TestParseWAVHeader_*`functions. Each now has minimal complexity.## [2026-05-04] Reduce cyclomatic complexity of handleKey (51 → 6)Refactored `Model.handleKey` in `tui/classify.go` from a single 51-complexitymonolith into 6 focused methods plus 2 utility helpers:- `handleKey` (6) — dispatcher routing to mode-specific handlers- `handleSecondaryWait` (6) — awaiting-secondary-calltype logic- `handleSpecialKey` (9) — Enter/Esc/Space/Ctrl+S- `handleSwitchKey` (14) — switch-based key dispatch- `handleBindingKey` (9) — single-char species/calltype bindings- `stopPlayer` — extracted repeated nil-check + Stop pattern- `advanceOrQuit` — extracted repeated next-segment-or-quit patternNo behavioral changes.