# Konsept: Orkestrering
**Filsti:** `docs/concepts/orkestrering.md`

## 1. Konsept

Orkestreringer er noder som *gjør* ting. De er oppskrifter —
sekvenser av CLI-verktøy og bot-instruksjoner som utføres
automatisk når en trigger aktiveres. Brukeren skriver hva som
skal skje i naturlig språk. Boten tolker og utfører.

## 2. Hvorfor

Synops har mange automatiseringer hardkodet i portvokteren:
podcast-pipeline, AI-beriking, publisering. De er usynlige,
uendrelige og umulige å tilpasse for brukere.

Orkestreringer gjør automatisering til førsteklasses graf-
primitiver — synlige, redigerbare, delbare, versjonerbare.

## 3. Nodemodell

```
node_kind: 'orchestration'
title: "Podcast: opptak → publisering"
content: "Når en innspilling avsluttes..."
metadata: {
  "trigger": {
    "event": "communication.ended",
    "conditions": {
      "has_trait": "podcast",
      "has_media": "audio"
    }
  },
  "executor": "bot",
  "intelligence": 2,
  "effort": 2,
  "compiled": false
}
```

### Tre typer noder som gjør

| node_kind | Ikon | Aktivering | Eksempel |
|-----------|------|------------|----------|
| `cli_tool` | 🔧 | Kalles av andre | synops-transcribe |
| `ai_preset` | 🔧 | Kalles av AI-verktøy | "Rens tekst"-prompt |
| `orchestration` | ⚡ | **Trigger-drevet, utfører seg selv** | Podcast-pipeline |

⚡ signaliserer: "denne noden gjør noe av seg selv."

## 4. Fritekst-instruksjoner

Stegene i en orkestrering er naturlig språk:

```
Når en innspilling i en samling med podcast-trait avsluttes:

1. Transkriber lydfilen med synops-transcribe (model: large)
2. Generer oppsummering med synops-summarize
3. Foreslå kapitler basert på transkripsjonen
4. Generer show notes
5. Oppdater RSS-feed med synops-rss

Hvis transkribering feiler, prøv igjen med model: medium.
Hvis RSS feiler, opprett work_item med tag 'bug'.
```

Brukeren skriver hva de vil. Boten tolker instruksjonene og
utfører med function calling — kaller CLI-verktøy via
portvokteren (se `docs/infra/robusthet.md` § function calling).

### Hvorfor fritekst, ikke DSL?

- Ingen DSL å lære for brukeren
- Boten resonnerer om feil og edge cases
- Feilhåndtering er naturlig ("hvis X feiler, prøv Y")
- Endring er å redigere tekst, ikke debugge JSON

## 5. Strukturert trigger

Triggeren er den eneste strukturerte delen — portvokteren
evaluerer den effektivt uten LLM:

```jsonc
{
  "trigger": {
    "event": "communication.ended",
    "conditions": {
      "has_trait": "podcast",
      "has_media": "audio"
    }
  }
}
```

### Kjente trigger-events

| Event | Beskrivelse |
|-------|-------------|
| `node.created` | Ny node opprettet |
| `edge.created` | Ny edge opprettet |
| `communication.ended` | Samtale/innspilling avsluttet |
| `node.published` | Node publisert (belongs_to med slot) |
| `scheduled.due` | Planlagt tidspunkt nådd |
| `manual` | Bruker trykker "Kjør" |

### Betingelser

Filtrerer triggeren ytterligere:
- `has_trait` — noden/samlingen har denne traiten
- `has_media` — noden har media-edge av denne typen
- `has_tag` — noden har tagged-edge med denne verdien
- `node_kind` — noden er av denne typen

## 6. Utførelse

### Bot-modus (default)

```
Trigger aktiveres
  → Portvokteren finner matchende orchestration-node
  → Sender til bot med function calling:
    - Trigger-kontekst (hvilken node, hvilken event)
    - Instruksjonene fra orchestration.content
    - Tilgjengelige verktøy (cli_tool-noder)
  → Boten utfører steg for steg
  → Logger hvert steg i orchestration_log
  → Ved feil: resonnerer og prøver alternativ
```

### Kompilert modus (optimalisert)

Når en orkestrering har kjørt mange ganger med samme mønster,
kan den kompileres til en direkte pipeline:

```jsonc
{
  "compiled": true,
  "pipeline": [
    { "tool": "synops-transcribe", "args_map": {"cas_hash": "input.cas_hash", "model": "large"} },
    { "tool": "synops-summarize", "args_map": {"communication_id": "input.id"} },
    { "tool": "synops-rss", "args_map": {"collection_id": "input.collection_id"} }
  ],
  "fallback": "bot"
}
```

Ingen LLM-kall for standardsteg. Direkte dispatch. Mye raskere,
billigere, deterministisk. `fallback: "bot"` betyr: ved feil
eller uventet situasjon, fall tilbake til fritekst-instruksjonene.

### Naturlig progresjon

```
1. Fritekst      → Brukere skriver, boten tolker
2. Observér      → Boten logger hvilke verktøy/sekvenser som gjentas
3. Foreslå       → "Denne har kjørt 50 ganger. Kompilere?"
4. Kompilér      → Fast pipeline, ingen LLM for standardsteg
5. DSL (senere)  → Kun hvis kompilerte pipelines trenger mer uttrykk
```

DSL-en designes ikke nå — den oppstår fra observerte mønstre.

## 7. Koblinger mellom orkestreringer

Orkestreringer er noder med edges:

```
"Podcast: opptak → publisering"
  ──triggers──→ "Varsle redaksjonen om ny episode"
  ──triggers──→ "Post til sosiale medier"
```

Output fra én orkestrering kan trigge neste via `triggers`-edge.
Kaskade via edges, ikke hardkodet.

## 8. Brukergrensesnitt

```
┌─ Podcastorkestrering ⚡ ──────────────────┐
│                                           │
│  Trigger: [Innspilling avsluttet ▼]       │
│  Betingelse: [Samling har podcast-trait ▼] │
│                                           │
│  Steg:                                    │
│  ┌─────────────────────────────────────┐  │
│  │ Transkriber lydfilen med stor       │  │
│  │ modell. Hvis det feiler, bruk       │  │
│  │ medium.                             │  │
│  ├─────────────────────────────────────┤  │
│  │ Oppsummer samtalen.                │  │
│  ├─────────────────────────────────────┤  │
│  │ Foreslå kapitler.                  │  │
│  ├─────────────────────────────────────┤  │
│  │ Oppdater RSS-feed.                 │  │
│  └─────────────────────────────────────┘  │
│                                           │
│  [+ Legg til steg]       [▶ Test kjøring] │
│                                           │
│  Status: Aktiv  Kjørt: 47 ganger          │
│  Sist: 2026-03-18 12:30 (OK)             │
└───────────────────────────────────────────┘
```

Hvert steg er en tekstboks. "Test kjøring" sender til boten
med dry-run. Historikk synlig.

## 9. Edge-modell

| Edge | Source → Target | Betydning |
|------|----------------|-----------|
| `belongs_to` | orchestration → collection | Tilhører denne samlingen |
| `observes` | orchestration → any node | Overvåker denne noden for trigger-events |
| `triggers` | orchestration → orchestration | Kaskade-kobling |
| `uses` | orchestration → cli_tool | Bruker dette verktøyet |
| `mentions` | orchestration → any | Refererer til denne noden |

### `observes`-edge: eksplisitt kobling

Orkestreringen peker på det den observerer:

```
"Auto-clip URL-er" (orchestration)
  ──observes──→ #Redaksjonen (communication)
  ──observes──→ #Research (communication)
```

Legg til `observes`-edge → aktivert for den noden.
Fjern edge → deaktivert. Samme orkestrering kan observere mange noder.

### Implisitt vs eksplisitt

- **`observes`-edge:** Eksplisitt. "Denne orkestreringen overvåker
  denne noden." Opprettet via drag-and-drop (se § interaksjonsmodell).
- **Trigger-betingelser:** Implisitt. "Overvåk alt som matcher."
- `observes` overtrumfer: fjernet `observes`-edge betyr "ikke her",
  selv om betingelsene matcher. Brukeren har kontroll.

## 10. Drømmemodus: brukeren skriver hva de vil

Brukeren begrenses ikke til kjente verktøy. De skriver fritt
— boten prøver, og mangler som oppdages blir feature requests.

### Slik fungerer det

```
Bruker skriver: "Lag en lydfil med sammendrag og send til deltakerne"

Boten sjekker:
  ✓ synops-summarize finnes → oppsummerer
  ✗ synops-tts finnes ikke → kan ikke lage lyd

Boten svarer i chatten:
  "Jeg oppsummerte møtet, men Synops har ikke tekst-til-tale
   ennå. Jeg oppretter en forespørsel?"

  → work_item i innboks:
    title: "TTS for møteoppsummeringer"
    tagged: "feature"
    source_material → orkestreringsnoden
```

Hver feilet steg som skyldes manglende verktøy er en **feature
request** — gratis, kontekstuell, fra faktisk behov. Systemet
lærer hva brukerne vil ha fra orkestreringer som ikke lykkes.

### Diskret hint, ikke begrensning

I editoren vises tilgjengelige verktøy som hint, men brukeren
kan skrive hva som helst:

```
┌─ Steg 3 ──────────────────────────────────┐
│ Lag en lydfil med oppsummeringen og send   │
│ den til alle deltakere                     │
│                                            │
│ ℹ Tilgjengelig: synops-tts, synops-rss,   │
│   synops-render, synops-transcribe...      │
│   (12 verktøy) — men skriv hva du vil     │
└────────────────────────────────────────────┘
```

Brukeren drømmer. Systemet vokser.

## 11. Avgrensning

- Orkestreringer er **ikke** en generell workflow-engine.
  De er oppskrifter som boten følger.
- Fritekst-instruksjoner er primær. Kompilering er
  optimalisering, ikke krav.
- Triggere evalueres av portvokteren, utførelse av boten.
  Klar ansvarsfordeling.
- Feilhåndtering er botens ansvar. Ingen retry-DSL.

## 12. Komponenter

| Feature | Rolle |
|---------|-------|
| Portvokteren | Evaluerer triggere, dispatcher til bot |
| @bot | Tolker instruksjoner, utfører med function calling |
| CLI-verktøy | Gjør det faktiske arbeidet |
| Arbeidstavlen | Work items opprettes ved feil |
| Responskvalitet | Intelligence/effort per orkestrering |

## 13. Bygger på
- `docs/retninger/unix_filosofi.md` — CLI-verktøy som byggeklosser
- `docs/concepts/arbeidstavlen.md` — @bot, work items ved feil
- `docs/infra/robusthet.md` — function calling, fallback
- `docs/features/responskvalitet.md` — intelligence/effort-nivåer
