# AGENTS.md

This repository is the native macOS SwiftUI port of BearWave, originally a
Linux/KDE internet radio app.

Do not treat it as a Qt compatibility port. The current repo is a native macOS
desktop app focused on internet radio.

## What This Repo Is

- SwiftPM macOS app targeting `macOS 26`
- SwiftUI desktop UI
- `AVPlayer`-based playback for radio streams
- Radio Browser as the station source
- Local persistence for favorites, recents, manual stations, station folders, and resume state

## Architecture Overview

- `Sources/BearWaveApp/BearWaveApp.swift`
  App scene entrypoint, window sizing, commands, menu bar extra, settings scene
- `Sources/BearWaveCore/App/AppModel.swift`
  Top-level app coordinator; owns `StationLibrary`, `PlaybackController`, and artwork services
- `Sources/BearWaveCore/Stores/StationLibrary.swift`
  Source of truth for station pages, search results, favorites, recents, manual entries, and station folders
- `Sources/BearWaveCore/Stores/PersistenceStore.swift`
  JSON-based persistence for radio state
- `Sources/BearWaveCore/Services/RadioBrowserClient.swift`
  Radio Browser API wrapper plus local search normalization and ranking
- `Sources/BearWaveCore/Services/PlaybackController.swift`
  Shared `AVPlayer` wrapper with explicit playback states, retries, stream metadata via `AVPlayerItemMetadataOutput`, and Now Playing updates
- `Sources/BearWaveCore/Services/StationArtworkLoader.swift`
  Favicon and artwork fetch with disk cache
- `Sources/BearWaveCore/Services/NowPlayingArtworkResolver.swift`
  Artwork resolution for current playback state
- `Sources/BearWaveCore/Views/`
  Sidebar, station list, station detail, player bar, settings, menu bar, mini player

## Current Product Behavior

- Dedicated pages:
  `Top`, `Germany`, `Netherlands`, `World`, `Search Results`, `Favorites`, `Recent`, `Manual`
- Search is global and stays independent from the current browse page
- Search ranking intentionally filters naive mid-word matches such as `slam` matching `Islamabad`
- Playback UI exposes explicit states: connecting, buffering, playing, paused, stopped, failed
- A right-side detail panel shows station metadata and current stream metadata when available
- Player controls remain radio-focused: play/pause, stop, volume
- Mini Player is available via `Cmd+M`
- Mini Player target size is `555x110`
- Station folders support create, rename, delete, and station assignment
- Menu bar extra remains active while playback continues

## Build and Run Conventions

Use these commands unless there is a strong reason not to:

```bash
swift build --disable-index-store
CLANG_MODULE_CACHE_PATH=/private/tmp/bearwave-clang-cache swift run --disable-index-store BearWaveChecks
./script/build_and_run.sh
```

The run script:

- kills the previous process
- builds via SwiftPM
- stages a local `.app` into `dist/`
- copies SwiftPM resource bundles manually
- copies `.lproj` localization directories into the bundle
- launches the app bundle

Do not remove the manual resource-bundle copy step from `script/build_and_run.sh`
unless the bundle pipeline is replaced deliberately.

## Important Constraints

- Prefer the internal SSD workspace:
  `/Users/sebastian/Development/radioappmac`
- Do not assume the mounted share copy is current.
- The staged app bundle uses ATS exceptions so that `http://` radio streams can play.
- Debug signing and sandbox behavior are intentionally pragmatic and not yet release-ready.
- `PlaybackController` uses `AVPlayerItemMetadataOutput` for stream metadata.
- `MediaPlayer` is imported with `@preconcurrency`.
- `MPMediaItemArtwork` is built from a `CGImage`-backed request handler.
- Main window launch width is dynamic: `1255` on smaller displays, `1600` on wide displays.
- Mini Player target size is `555x110`.

## What To Preserve

- Keep the project native-first for macOS.
- Keep search global and ranking strict.
- Keep explicit playback states; do not regress to a plain boolean model.
- Keep the current split between `BearWaveApp` and `BearWaveCore`.
- Keep the build/run script compatible with local staged app execution.

## Good Next Steps

- Improve release packaging, signing, and notarization
- Add more playback diagnostics per stream failure mode
- Expand tests around playback-state transitions and search ranking
- Add cache eviction for memory and disk caches
- Keep folders clearly positioned as lightweight saved-station organization

## Bad Changes

- Reintroducing page-coupled search behavior
- Replacing explicit playback states with only `isPlaying`
- Moving back toward Qt/KDE abstractions in this repo
- Assuming every stream will provide usable metadata or artwork
