# Feature: Lydmeldinger & Diktering
**Filsti:** `docs/features/lydmeldinger.md`

## 1. Konsept
En mobil-first talefeature med tre moduser som dekker spekteret fra kjappe chatmeldinger til langt feltopptak. Grunnprinsippet er det samme: **du snakker inn i telefonen, og systemet gjør noe nyttig med det**. Forskjellen er hva som er output.

| Modus | Typisk lengde | Output | Master-format | Lagring |
|---|---|---|---|---|
| **Voice-to-text** | <30 sek | Rå transkripsjon i meldingsfeltet | Tekst | Ingen (lyden kastes) |
| **Lydmelding** | <10 min | Lydfil + transkripsjon for søk | Lyd | `media_file` + node i grafen |
| **Diktering** | 1–30 min | AI-ryddet tekst (strukturert notat) | Tekst | Node i grafen |

Voice-to-text er en del av chat-featuren (se `docs/features/chat.md`, seksjon 8). Denne specen dekker de to tyngre modusene.

## 2. Lydmelding-modus

### 2.1 Brukerflyt
1. Bruker åpner lydmelding-modus (via FAB-knapp, hurtigtast eller fra en channel).
2. Trykker record. Nettleseren fanger lyd via `MediaRecorder` API (WebM/Opus).
3. Kan valgfritt velge kontekst: et Tema, en Aktør, eller "Usortert".
4. Ved stopp lastes lydfilen opp til SvelteKit (streaming for store filer).
5. Filen lagres som `media_file` i mediamappen (`/srv/synops/media/voice/`).
6. En `whisper_transcribe`-jobb opprettes i jobbkøen for å gjøre opptaket søkbart.
7. Transkripsjonen lagres som metadata på noden — lydfilen forblir master.

### 2.2 Datamodell
Lydmeldingen er en node i Kunnskapsgrafen (`node_type = 'melding'`, `message_type = 'voice_memo'`):

```
nodes (node_type = 'melding')
  → messages (channel_id, message_type = 'voice_memo', body = transkripsjon, metadata = { duration, transcription_status })
  → message_attachments → media_files (lydfilen)
```

Lydmeldinger kan:
- Sendes i en channel (som vedlegg til en melding)
- Leve fristående i en personlig "Innboks"-channel
- Knyttes til Temaer/Aktører via `graph_edges` (manuelt eller AI-foreslått)

### 2.3 Triagering
Redaksjonen trenger en flate for å gå gjennom nye lydmeldinger:
- Lytt, tagg med Temaer/Aktører
- Marker for bruk i episode (kobles til Kanban/Kjøreplan)
- Forkast / arkiver
- Denne flaten er en filtrert visning av "Innboks"-channelen, ikke et eget system

### 2.4 Bruk i podcast
Lydmeldinger markert for bruk kan trekkes inn i Podcastfabrikkens pipeline. Lydfilen er allerede i media-mappen — den kan klippes inn i en episode direkte.

## 3. Dikteringsmodus

### 3.1 Brukerflyt
1. Bruker åpner dikteringsmodus (mobil-first, men fungerer på desktop).
2. Snakker fritt — kan være flere minutter. Visuell indikator viser at opptak pågår.
3. Ved stopp opprettes to jobber i jobbkøen (sekvensielt):
   - `whisper_transcribe` — rå transkripsjon (`medium` + `initial_prompt` for kvalitet)
   - `dictation_cleanup` — AI rydder i teksten
4. Brukeren ser resultatet: rå transkripsjon og AI-ryddet versjon side om side.
5. Kan redigere den ryddede versjonen før lagring.
6. Lagres som et notat (node i grafen). Lydfilen slettes etter vellykket transkripsjon.

### 3.2 AI-opprydding (`dictation_cleanup`)
AI Gateway (`sidelinja/rutine`) prosesserer transkripsjonen med instruksjon om å:
- Fjerne fyllord, gjentakelser og ufullstendige setninger
- Strukturere i avsnitt med overskrifter der det gir mening
- Bevare talerens mening og tone — ikke omskrive til "AI-språk"
- Foreslå `#Tema`- og `@Aktør`-tags basert på innholdet

### 3.3 Datamodell
Dikterte notater er meldinger i en channel:

```
nodes (node_type = 'melding')
  → messages (channel_id, message_type = 'text', body = ryddet tekst, metadata = { raw_transcript, source: 'dictation' })
```

Metadata bevarer rå-transkripsjonen slik at brukeren alltid kan se hva som faktisk ble sagt.

### 3.4 Målkanal
Brukeren velger hvor notatet havner:
- **Personlig notat-channel** — default, kun synlig for brukeren selv
- **Tema-channel** — delt med redaksjonen som et innspill
- **Direkte til en annen bruker** — som en asynkron "talemelding i tekstform"

## 4. Felles infrastruktur

### 4.1 Opptak (klient)
Begge moduser bruker samme opptakskomponent i SvelteKit:
- `MediaRecorder` API med WebM/Opus
- Visuell feedback (lydnivå-indikator, varighet)
- Modus-velger: Lydmelding / Diktering
- Kontekst-velger: Tema, Aktør, eller Usortert

### 4.2 Opplasting
SvelteKit håndterer filopplasting strømmende. For korte klipp (<2 min) kan opplasting starte umiddelbart etter stopp. For lengre opptak bør det vises en fremdriftsindikator.

### 4.3 Whisper
Begge moduser bruker live transkripsjonspipelinen (se `docs/features/live_transkripsjon.md`) i batch-modus via jobbkøen. Modellvalg:
- Lydmelding: `small` (rask, transkripsjonen er sekundær — lyden er master)
- Diktering: `medium` + `initial_prompt` (kvalitet prioritert — teksten er master)

### 4.4 Personlig "Innboks"-channel
Ved brukeropprettelse opprettes en privat channel per bruker for usorterte lydmeldinger og notater. Config:

```json
{
  "threads": false,
  "mentions": false,
  "attachments": true,
  "research_clips": false,
  "ttl_days": null
}
```

## 5. Dataklassifisering (ref. docs/arkitektur.md 2.2)

| Data | Kategori | Detaljer |
|---|---|---|
| Lydfiler (voice memos) | Kritisk (backup) | Unikt råmateriale — lyden *er* innholdet, kan brukes direkte i podcasten |
| Diktert tekst (ryddet) | Kritisk (PG) | Brukerens innhold |
| Rå transkripsjon | Avledet | Kan regenereres fra lydfil |
| Lydfil fra diktering | Flyktig (TTL) | Lyden er kun et *transportformat* for teksten — slettes etter at brukeren har godkjent den ryddede teksten. Spart diskplass, og unngår å lagre halvformulerte tanker som lyd. |

## 6. Jobbtyper

| Jobbtype | Modellalias | Beskrivelse |
|---|---|---|
| `whisper_transcribe` | — | Eksisterende jobbtype, gjenbrukes |
| `dictation_cleanup` | `sidelinja/rutine` | AI-opprydding av transkripsjon |

## 7. Instruks for Claude Code
* Opptakskomponenten skal være en gjenbrukbar Svelte-komponent med modus-prop (`voice_memo` / `dictation`).
* Lydfiler lagres i `media/voice/` — aldri i databasen.
* Diktering: slett lydfilen først *etter* at brukeren har godkjent den ryddede teksten.
* `voice_memo` er en ny `message_type` — utvid enum i migrasjonen.
* Personlig innboks-channel opprettes automatisk for nye brukere.
* Tilgang styres via `node_access`-matrisen.
