---
name: add-feature
description: Add a new feature to the audio_samples_io Rust codebase following its established patterns. Use this whenever the user asks to add, implement, or build anything new in audio_samples_io — a new audio format, a new trait, a new utility, a new API endpoint, or any new capability. Also triggers for "extend the codebase", "support for X format", "add streaming support for Y", "implement Z". Automatically chains simplify, rust-perf-review, pre-commit, and commit for a clean, tested, committed result.
version: 1.0.0
allowed-tools: [Read, Bash, Edit, Write, Glob, Grep, Agent]
---

# Add Feature — audio_samples_io

Systematic process for adding a new feature to this Rust audio I/O library. The goal is code that fits seamlessly — same style, same performance bar, same error handling, same clippy discipline.

## Phase 1: Understand the Request

Capture what the user wants:
- What capability should the feature add? (new format, new trait method, new utility, new API?)
- Which existing features/formats is it analogous to?
- Any hard constraints (performance budget, API surface, backward compat)?

If the request is vague, ask one focused question before exploring. Don't ask multiple questions at once.

## Phase 2: Explore Relevant Patterns

Before touching any code, read the analogous existing implementation. The two reference implementations to lean on are:

- **WAV format**: `src/wav/` — battle-tested, covers all trait impls, streaming reader/writer, error handling
- **FLAC format**: `src/flac/` — more recent, pure-Rust decoder, shows layered module structure

For **trait additions or utility features**, also read:
- `src/traits.rs` — the full trait hierarchy
- `src/types.rs` — `ValidatedSampleType`, `BaseAudioInfo`, `OpenOptions`
- `src/error.rs` — `AudioIOError`/`AudioIOResult` patterns

Ask: what is the closest existing thing to what we're building?

## Phase 3: Clarify Edge Cases

After reading the code, surface any open questions — especially around:
- Sample types supported (not all formats support all `ValidatedSampleType` variants)
- Error conditions (what can go wrong? what error variant fits?)
- Streaming vs. batch (should this be read-all-at-once, or add `AudioStreamRead`?)
- Feature gate (does this need a new Cargo feature, or fold into an existing one?)
- Performance expectations (hot path? cold path? benchmark worthy?)

Present a short list. Wait for answers.

## Phase 4: Design the Module Structure

Map out what files need to exist or change. Use this as a guide:

### Adding a new format (e.g. MP3, OGG, AIFF)

```
src/<format>/
├── mod.rs          # module-level docs, re-exports, public API
├── error.rs        # format-specific error type (mirrors wav/error.rs, flac/error.rs)
├── <format>_file.rs  # the main struct implementing AudioFile + AudioFileMetadata + AudioFileRead
├── constants.rs    # magic bytes, limits, codec constants
└── (streaming.rs)  # if adding streaming support
```

Changes to existing files:
- `src/lib.rs` — `#[cfg(feature = "...")]` module declaration + re-exports
- `src/error.rs` — new `#[error("...")]` variant `#[cfg(feature = "...")]`
- `Cargo.toml` — new feature + dependencies
- `src/types.rs` — add to `FileType` enum if it doesn't exist

### Adding a trait method or utility

- Add to `src/traits.rs` (with a default impl if reasonable)
- Implement in the relevant format modules
- Update re-exports if the utility is public

### Adding a new public API function

- Add to `src/lib.rs` following the existing `read`, `write`, `info`, `open_streamed` pattern

## Phase 5: Implement

Follow these rules — they encode the project's conventions and clippy lints:

### Error handling
- Use `AudioIOResult<T>` as the return type for everything fallible.
- Return meaningful `AudioIOError` variants. Use `AudioIOError::corrupted_data_simple(description, details)` for parse failures.
- **Never use `.unwrap()` or `panic!()`** — the project has `#![warn(clippy::unwrap_used)]` and `#![warn(clippy::panic)]`. Use `?` or explicit error conversion.
- For format-specific errors, add a new error type under `src/<format>/error.rs` and a `From` impl into `AudioIOError`.

### Performance
- Large reads should use `memmap2::Mmap` when the file exceeds `MAX_MMAP_SIZE` (512 MB). See `wav_file.rs` for the pattern.
- Use `BufReader`/`BufWriter` for smaller sequential I/O.
- Avoid allocations in hot paths. Prefer reusing buffers (`read_frames_into` pattern) over allocating per-call.
- The clippy lints `#![warn(clippy::needless_collect)]`, `#![warn(clippy::map_clone)]`, and `#![warn(clippy::redundant_clone)]` are active — respect them.

### Feature gating
- New format = new Cargo feature. Pattern: `#[cfg(feature = "flac")]` in `lib.rs` and `error.rs`.
- Keep the default feature set minimal (`default = ["wav"]`).
- Add the new feature to the `full` alias if it's a first-class format.

### Trait implementations
For a new format, implement in this order (each depends on the last):
1. `AudioFile` — `open_with_options`, `len`
2. `AudioFileMetadata` — `base_info`, `specific_info`, `file_type`, `file_path`, `total_samples`, `duration`, `sample_type`, `num_channels`
3. `AudioFileRead` — `read<T>`, `read_into<T>`
4. `SupportsSampleTypes<N>` — list the supported sample types
5. `AudioStreamReader` + `AudioStreamRead` — only if streaming is in scope

### Module docs
The `mod.rs` for each format has a module-level doc comment (see `src/flac/mod.rs` for the pattern). Write one for new modules — cover: what the format is, what's implemented, any limitations.

### Re-exports
- In `src/<format>/mod.rs`: re-export the main struct and any public types.
- In `src/lib.rs`: re-export through the feature gate.

### ValidatedSampleType matching
All `match value { ... }` on `SampleType` must have a wildcard arm `_ => ...` because `SampleType` is `#[non_exhaustive]`.

## Phase 6: Write Tests

Integration tests live in `tests/`. Add a new file `tests/<format>_read.rs` (and `tests/<format>_write.rs` if applicable), mirroring the pattern in `tests/wav_read.rs`:
- Cross-validate against a reference implementation where one exists
- Test exact sample values for small known inputs
- Test metadata (sample rate, channels, sample type, duration)
- Test boundary conditions (first/last sample, empty/near-empty files)

Run tests (adjust feature flags as needed):
```bash
cargo test --features <feature> --lib
cargo test --features <feature>
```

## Phase 7: Quality Gates

Run these in order — each one must pass before proceeding to the next.

### 1. Simplify
Invoke the **simplify** skill on the new/changed files. This catches redundant code, style drift, and missed idiomatic patterns.

### 2. Performance Review
Invoke the **rust-perf-review** skill. This is a Rust project with a high performance bar — new code should not introduce avoidable allocations, unnecessary clones, or inefficient buffer patterns.

### 3. Pre-commit
Invoke the **pre-commit** skill. This runs `cargo fmt --all` and `cargo clippy --all-targets --all-features -- -D warnings`. The build must be clean.

## Phase 8: Commit

Invoke the **commit** skill. The commit message should follow Conventional Commits:
- `feat(<format>): add <format> read/write support` for new formats
- `feat(traits): add <method> to AudioStreamRead` for trait additions
- `feat(api): add <function> to top-level API` for API additions

## Quick Checklist

Before calling the work done, verify:
- [ ] No `.unwrap()` or `panic!()` in new code
- [ ] All `SampleType` matches have a `_` wildcard arm
- [ ] Feature gate added in `Cargo.toml`, `lib.rs`, and `error.rs`
- [ ] Re-exports added in `mod.rs` and `lib.rs`
- [ ] Integration tests written and passing
- [ ] simplify + rust-perf-review + pre-commit all pass
- [ ] Commit created with changelog
