# TASK-006

## Title

Feature Storage and Analysis Persistence

---

## Objective

Implement persistent storage for analyzer results.

Starting from this task, every analyzer must be able to save its calculated features into SQLite.

The storage layer must support:

- analyzer versioning
- incremental analysis
- future analyzer upgrades
- selective re-analysis
- immutable feature history

This task introduces the permanent storage model for the analysis system.

No new DSP algorithms should be implemented.

---

# Expected Commit Message

Add feature storage

---

# Requirements

Read SPEC.md before implementing anything.

Follow all AI Rules.

Follow the Analysis Framework introduced in TASK-004.

Do not violate architectural boundaries.

---

# Scope

Create a new package

```
src/storage/
```

Files

```
__init__.py
feature_repository.py
analysis_repository.py
```

---

# Database Models

Create new ORM models.

---

## AnalyzerRun

Represents one execution of one analyzer.

Fields

```
id

track_id

analyzer_name

analyzer_version

started_at

finished_at

execution_time_ms

success

warnings
```

---

One AnalyzerRun exists for every analyzer execution.

---

## TrackFeature

Represents one calculated feature.

Fields

```
id

track_id

analyzer_run_id

name

value

unit

created_at
```

---

Rules

One row = one feature.

Never overwrite.

Never update.

Never delete.

---

# Repository Layer

Implement

```
AnalysisRepository
```

Responsibilities

- create AnalyzerRun

- finish AnalyzerRun

- mark failed AnalyzerRun

- list analyzer history

---

Implement

```
FeatureRepository
```

Responsibilities

- save FeatureSet

- query features by track

- query features by analyzer

- query latest analyzer run

- query latest FeatureSet

Repositories are the only layer allowed to access SQLAlchemy.

---

# Pipeline Integration

Modify AnalysisPipeline.

Workflow

```
Analyzer

↓

AnalysisResult

↓

AnalysisRepository

↓

FeatureRepository
```

Pipeline automatically persists successful analyzer results.

No analyzer may perform database operations.

---

# CLI

Existing

```
musimuse analyze
```

must now

- run analyzers

- store AnalyzerRun

- store FeatureSet

- print

```
Tracks analyzed

Analyzer runs

Features stored

Failures
```

---

# Analyzer Versioning

Analyzer version is now part of persistence.

Example

```
basic_signal

1.0.0
```

Later

```
basic_signal

1.1.0
```

Both versions must be allowed to coexist.

History must never be destroyed.

---

# Idempotency

Running

```
musimuse analyze
```

twice on the same analyzer version

must NOT create duplicate features.

Expected behavior

```
latest analyzer version already exists

↓

skip analysis
```

unless

```
--force
```

is introduced later.

---

# Query API

FeatureRepository should expose

```
get_track_features(track)

get_latest_features(track)

get_feature(track, name)

list_analyzer_runs(track)

has_analyzer_version(track)
```

---

# Logging

Pipeline should log

```
analysis.saved

analysis.skipped

analysis.failed

feature.saved

feature.count
```

Repositories must not log.

Analyzers must not log.

---

# Tests

Create tests for

AnalyzerRun creation

AnalyzerRun completion

AnalyzerRun failure

Feature persistence

Feature lookup

Latest feature lookup

History lookup

Version lookup

Idempotent execution

Pipeline persistence

Repository isolation

Database constraints

Multiple analyzer versions

Multiple tracks

Failure handling

---

# Forbidden

Do NOT implement

FFT

Tempo

Harmony

Similarity

Music DNA

Recommendations

Embeddings

Caching

Parallel execution

---

# Definition of Done

✓ AnalyzerRun model implemented

✓ TrackFeature model implemented

✓ AnalysisRepository implemented

✓ FeatureRepository implemented

✓ Pipeline automatically persists results

✓ Analyzer version stored

✓ Feature history preserved

✓ Duplicate analyzer execution skipped

✓ Query API implemented

✓ CLI stores features

✓ Tests pass

✓ Ruff passes

✓ Black passes

✓ isort passes

---

# Architectural Notes

Starting with this task, analyzer output becomes persistent.

Analyzers remain completely stateless.

The pipeline owns persistence.

Repositories own SQLAlchemy access.

Features become immutable records.

Analyzer executions become immutable history.

This design enables:

- analyzer upgrades

- reproducible analysis

- selective re-analysis

- future Music DNA generation

- similarity search

without changing analyzer implementations.