synops/docs/retninger/universell_input.md
vegard c1d3ad66a5 Fjern gjenværende v2-referanser, dokumenter editor og tekstlagring
Rydder opp siste «v2»-referanser i docs (status_quo, migration_safety,
personlig_workspace, spacetimedb_integrasjon). Legger til editor-seksjon
i universell_input.md (TipTap, presets, tekstlagring) og oppdaterer
nodes.md med content/metadata.document-modellen.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 10:55:39 +01:00

260 lines
8.6 KiB
Markdown

# Universell input og mottak
**Status: Besluttet.**
> Én multimodal input-primitiv. Én personlig mottaksflate. Alt som
> fanges er en node. Hva det "er" bestemmes av edges. Hvordan det
> presenteres bestemmes av mottakeren.
## Input-primitiven
Én overflate som fanger alt:
- **Tekst** — skriving, Markdown, kodeblokker
- **Lyd** — voice memo, diktering → automatisk transkribert
- **Bilde** — foto, skjermbilde, tegning
- **AI-støtte** — spør AI, få forslag, la den transformere input
- **URL** — lim inn lenke, den berikes automatisk
Brukeren gjør det samme uansett kontekst — skriver, snakker eller
tegner i input-feltet. Forskjellen mellom "dagbok", "chatmelding"
og "kanban-kort" er ikke hva brukeren gjør — det er hvilke edges
som knyttes til resultatet.
### Én pipeline
All input går gjennom samme tekniske pipeline:
maskinrommet → SpacetimeDB (instant) → PG (asynk).
Konteksten bestemmer routing, ikke en teknisk modus:
- Du er i et møte → inputen streames live til andre deltakere
- Du er alene på bussen → inputen lander som privat node
- Du er i en podcast-kanal → inputen går inn i produksjonspipeline
Samme pipeline. Ulike edges.
### Input-metode og innholdstype er ortogonale
Du kan snakke inn et kanban-kort. Du kan tegne en kalenderoppføring.
Input-primitiven bryr seg ikke om hva det *blir* — den fanger det
som kommer inn. Alt etterpå er edges.
### Én overflate å perfeksjonere
All UX-investering konsentreres ett sted. Én perfekt input-opplevelse
— responsiv, multimodal, med god AI-støtte — i stedet for ti
middelmådige spesialgrensesnitt.
## Editoren
Input-komponenten er en TipTap-editor (ProseMirror-basert) som
konfigureres med ulike extensions basert på kontekst.
### Kontekst setter default, brukeren bestemmer
Konteksten (kommunikasjonsnoden du er i, visningen du bruker)
setter en *default* editor-konfigurasjon. Men brukeren kan alltid
overstyre — utvide til full editor eller forenkle. Ingen kunstig
grense mellom "chatmelding" og "artikkel."
Du *kan* skrive en gjennomformatert tekst med overskrifter, bilder
og blockquotes i chatten. Om du vil publisere den etterpå er det
bare å legge til en publiserings-edge. Innholdet er det samme.
Editoren husker brukerens valg per kontekst via preferanser på
brukernoden.
### Presets
| Kontekst | Default extensions | Eksempel |
|----------|-------------------|----------|
| Chat | Tekst, markdown, kodeblokker, lenker | Enkel melding |
| Artikkel/blogg | + overskrifter, bilder, embeds, blockquotes, tabeller | Publisert tekst |
| Show notes | + lister, tidskoder, lenker | Episodenotater |
| Kanban-kort | Tekst, sjekklister | Oppgavebeskrivelse |
Presets er bare default — brukeren kan utvide eller forenkle med
en knapp eller tastatursnarvei. Ikke en modebytte, bare at flere
verktøy blir tilgjengelig.
### Tekstlagring
Noden lagrer to representasjoner:
- `content TEXT` — ren tekst uten formatering, for fulltekstsøk
og enkel visning
- `metadata.document JSONB` — strukturert TipTap/ProseMirror-
dokument for rendering
```json
{
"type": "doc",
"content": [
{ "type": "paragraph", "content": [
{ "type": "text", "text": "Her er en intro." }
]},
{ "type": "image", "attrs": {
"node_id": "uuid-av-cas-node", "alt": "Diagram"
}},
{ "type": "paragraph", "content": [
{ "type": "text", "text": "Teksten fortsetter." }
]}
]
}
```
`content` genereres automatisk fra dokumentet ved lagring — bare
teksten, uten markup. Editoren produserer begge.
For enkle meldinger (ren tekst uten formatering) er
`metadata.document` null — `content` er alt som trengs.
### Bilder og media i tekst
Bilder i dokumentet refererer til CAS-noder via `node_id`.
CAS-noden er en egen node med `has_media`-edge til innholdsnoden.
Dokumentstrukturen bestemmer *hvor* bildet plasseres i teksten.
Tekst er *på* noden. Binærfiler er *andre* noder koblet med edges.
Ren separasjon: tekst er innhold, binærfiler er vedlegg som kan
plasseres inline.
## Edges definerer alt
Hva en node "er" bestemmes utelukkende av edges:
- Node + `belongs_to` → kanal = chatmelding
- Node + `belongs_to` → board + `status` = kanban-kort
- Node + `scheduled` → tidspunkt = kalenderoppføring
- Node uten edges til andre = privat notat
- Node + `mentions` → topic = faktoid i kunnskapsgrafen
- Node uten edges = løs tanke, ennå uorganisert
**Retyping er trivielt.** Chatmelding → kanban-kort = legg til
board-edge og status-edge. Ingen datamigrering, bare edges.
**Multitype er naturlig.** En node kan være *både* kanban-kort
*og* kalenderoppføring *og* faktoid. Det er ikke en edge case —
det er arkitekturen.
### Edge-tildeling
Når du "bare sier noe" — hvem bestemmer edges?
1. **Kontekst gir det meste.** Du er i en samtale → `belongs_to`-
edge til samtalen. Du er alene → privat. Dekker 80%.
2. **Eksplisitt handling.** Du drar en node til kanban-brettet.
Du tagger noe. Du setter en dato.
3. **AI-foreslått.** Systemet foreslår `mentions`-edge når du
nevner en person. Foreslår kanban når noe ligner en oppgave.
Detaljer for AI-foreslåtte edges avklares ved implementering.
## Mottak-primitiven
Der input er "én overflate som fanger alt", er mottak "én overflate
som presenterer alt tilpasset *deg*."
### Mottaker bestemmer format
All lyd transkriberes. All tekst kan leses opp (TTS). Noden har
alltid begge representasjoner. Mottaker setter sin preferanse:
- Trond snakker inn en tanke → node med lyd + transkripsjon
- Peter har tekst-preferanse → ser transkripsjonen
- Vegard har lyd-preferanse → hører originallyd
Modalitet er ikke en egenskap ved meldingen, men ved *lesningen*.
### Dimensjoner ved mottak
**Format.** Lyd, tekst, visuelt — mottaker bestemmer.
**Filtrering.** Mottaksflaten filtrerer basert på dine edges:
kanaler du følger, personer du samarbeider med, topics du er
interessert i.
**Prioritering.** AI-assistert vekting: ubesvarte meldinger,
oppgaver med frist, noder endret siden sist. Ikke en
notifikasjonsliste — en vektet visning av det som er relevant.
**Tempo.** Sanntid (ting streamer inn) eller asynkront (digest,
oppsummering).
### Mottaksflaten er en visning av grafen
"Noder med edge til *meg*, vektet på relevans og tid." Ikke en
egen mekanisme — en spørring mot grafen med deg som sentrum.
## Kommunikasjonsnoden — den tredje primitiven
Input fanger. Mottak presenterer. Kommunikasjonsnoden er *stedet*
der folk møtes — en node som samler deltakere, definerer
tilgangsregler, og fungerer som kontekst.
### Én node, mange former
| Variant | Deltakere | Input | Mottak |
|---------|-----------|-------|--------|
| Én-til-én | 2 | Begge | Begge |
| Gruppechat | N | Alle | Alle |
| Møte | N | Alle | Alle |
| Allmøte | 1 + N | Leder | Alle lytter |
| Podcastinnspilling | 2-4 + N | Verter | Alle lytter |
| Livesending | 1-4 + ∞ | Verter | Streamet |
| Asynkron gjest | 1 + 1 | Gjest | Redaksjonen |
Forskjellen er edge-konfigurasjoner, ikke ulike systemer:
- `owner`-edge — kontrollerer noden
- `member`-edge — kan gi input og motta
- `reader`-edge — kan kun motta
### Kontekst arves automatisk
Input i en kommunikasjonsnode arver kontekst-edges. Sier du noe
i et møte → noden får `belongs_to`-edge til møtet automatisk.
### Livssyklus
- **Live** — deltakere til stede, input streames
- **Asynkron** — deltakere gir input i eget tempo
- **Avsluttet** — arkivert, alt som ble sagt er noder med edges
- **Gjenåpnet** — reaktivert ("vi tar opp tråden fra forrige møte")
### Skalering er edge-endring
Samtale → møte = flere deltaker-edges.
Møte → livesending = offentlige mottak-edges.
Livesending → podcast = publiserings-edges på arkivert innhold.
## Tekniske forutsetninger
### STT (tale → tekst): løst
Faster-whisper kjører lokalt, god norsk kvalitet.
### TTS (tekst → tale): løsbart
Start med ElevenLabs bak AI Gateway, bytt til lokal modell når
kvaliteten holder. Backend-swap bak gatewayen — brukeren merker
ingenting.
## Visninger er spørringer
Chat = noder med kanal-edge, sortert på tid.
Kanban = noder med board-edge, gruppert på status.
Kalender = noder med dato-edge, på tidslinje.
Dagbok = private noder, sortert på tid.
Mottaksflate = noder med edge til deg, vektet.
Alle leser fra samme graf. Ingen har "sin egen" data.
## Forhold til andre retninger
- [Noder er sentrum](bruker_ikke_workspace.md) — visibility,
tilgangsmatrise, aliaser
- [Datalaget](datalaget.md) — SpacetimeDB holder hele grafen,
PG persisterer asynkront
- [Maskinrommet](maskinrommet.md) — validering, routing, CAS,
tunge jobber (Whisper, TTS, AI)
- [Rom, ikke forum](rom_ikke_forum.md) — kommunikasjonsnoden
er den konkrete realiseringen av "rommet"