synops/docs/concepts/orkestrering.md
vegard e0988711d8 Spesifiser interaksjonsmodell: drag-and-drop som universell grammatikk
Ny retning som formaliserer Synops sin interaksjonsfilosofi:
- Inn=transformer, ut=skap nytt (to retninger)
- Body=engang, header=vedvarende (to mål)
- Konsistent overalt: AI, orkestrering, tema, lyd, kalender
- Visuell feedback med to drop-soner (grønn=engang, blå=vedvarende)
- Fire prinsipper: reversibilitet, konsistens, synlighet, gradvis dybde

Også: observes-edge i orkestrering og edges.md for eksplisitt
kobling mellom orkestrering og observerte noder.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 13:41:06 +00:00

309 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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