Commit graph

96 commits

Author SHA1 Message Date
c0b89949e3 Opprydding: arkiver STDB-docs, fjern Caddy-konfig, rydd referanser (oppgave 22.5)
SpacetimeDB ble fjernet i 22.4. Denne oppryddingen:
- Arkiverer spacetimedb_integrasjon.md og adapter_moenster.md til docs/erfaringer/arkiv/
- Fjerner SpacetimeDB reverse proxy-blokk fra Caddyfile
- Fjerner SpacetimeDB-loven fra Claude feedback-memories (ikke lenger relevant)
- Oppdaterer docs-referanser i CLAUDE.md, erfaringer/README.md,
  selvdokumenterende_system.md og tasks.md
- Markerer fase 22 som fullført i avhengighetsgrafen
2026-03-18 13:45:30 +00:00
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
b5aa5bb243 Fjern SpacetimeDB komplett (oppgave 22.4)
SpacetimeDB er nå helt fjernet fra Synops. Sanntid håndteres av
PG LISTEN/NOTIFY + WebSocket i portvokteren (maskinrommet).

Kode fjernet:
- spacetimedb/ Rust-modul og spacetime.json
- maskinrommet/src/stdb.rs (HTTP-klient for STDB-reducers)
- frontend module_bindings/ (23 auto-genererte filer)
- spacetimedb npm-avhengighet fra package.json
- scripts/test-sanntid.sh (testet STDB-flyt)

Infrastruktur:
- Docker-container stoppet og fjernet fra docker-compose.yml
- Caddy: fjernet /spacetime/* reverse proxy
- maskinrommet-env.sh: fjernet STDB_IP og SPACETIMEDB_*-variabler
- .env.example: fjernet SpacetimeDB-seksjoner

Dokumentasjon oppdatert:
- CLAUDE.md: stack, lagmodell, kjerneprinsipper, driftsmodell
- docs/arkitektur.md: skrivestien, lesestien, datalag, teknologivalg
- docs/retninger/datalaget.md: migrasjonshistorikk, status "fjernet"
- 37 andre docs oppdatert (features, concepts, infra, ops, retninger)
- Alle kode-kommentarer med STDB-referanser oppdatert

Verifisert: maskinrommet bygger og starter OK, frontend bygger OK,
helsesjekk returnerer 200. Caddy reloadet.
2026-03-18 13:39:09 +00:00
118a6741ce Legg til drømmemodus i orkestrering: brukeren skriver fritt, mangler blir feature requests
Brukeren begrenses ikke til kjente verktøy. Boten prøver,
og manglende funksjonalitet fanges opp som work_items med
source_material-edge tilbake til orkestreringen. Systemet
lærer hva brukerne vil ha fra det som ikke lykkes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 13:22:04 +00:00
79acf0bb0a Spesifiser orkestrering: trigger-drevne noder som utfører seg selv
Nytt konseptdokument for orchestration-noder ():
- Fritekst-instruksjoner som boten tolker og utfører
- Strukturerte triggere (portvokteren evaluerer uten LLM)
- Naturlig progresjon: fritekst → observér → kompilér → DSL
- Kompilerte pipelines med bot-fallback ved feil
- Kaskade mellom orkestreringer via triggers-edges
- Visuell editor med tekstbokser per steg og test-kjøring

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 13:17:53 +00:00
aee6adc425 Fjern STDB-skrivestien: all skriving går kun til PG (oppgave 22.3)
SpacetimeDB var brukt som «instant feedback»-lag mellom portvokteren
og frontend. Nå som PG NOTIFY-triggere og WebSocket er på plass
(oppgave 22.1–22.2), er STDB-skrivestien overflødig.

Endringer:
- intentions.rs: Alle CRUD-operasjoner (create/update/delete node/edge)
  skriver nå synkront til PG i stedet for STDB-først + async PG-jobbkø.
  PG NOTIFY-triggere gir umiddelbar sanntidsoppdatering til klienter.
  Tilgangsgivende edges (owner/admin/member_of/reader) bruker transaksjon
  med recompute_access direkte i handleren.
- maintenance.rs: Fjernet StdbClient fra alle funksjoner. Varsler
  opprettes/oppdateres/slettes direkte i PG.
- agent.rs, audio.rs, tts.rs, ai_process.rs: Fjernet STDB-synk etter
  CLI-verktøy-kjøring. PG NOTIFY dekker sanntidsvisning.
- pg_writes.rs: Fjernet sync_node_access_to_stdb. access_changed
  NOTIFY-trigger håndterer dette.
- workspace.rs: Synkrone PG-skrivinger med recompute_access.
- summarize.rs, ai_edges.rs: Fjernet StdbClient fra signaturer.
- jobs.rs: Fjernet StdbClient fra dispatch og start_worker.
- main.rs: Fjernet STDB-initialisering, warmup, stdb_monitor.
  StdbClient fjernet fra AppState. stdb.rs beholdt som død kode
  (fjernes i oppgave 22.4).
- health.rs: Fjernet STDB-helsesjekk fra dashboard.
- Slettet warmup.rs og stdb_monitor.rs (PG→STDB-synk ikke lenger
  relevant).
- docs/retninger/datalaget.md: Markert fase M3 som fullført.
2026-03-18 13:11:33 +00:00
71d9bbf25f Spesifiser synops-manual: komplett teknisk instruksjonsmanual fra faktisk tilstand
Ny feature-spec for selvgenererende systemmanual:
- Genereres fra faktisk tilstand (PG-skjema, systemd, Docker, CLI)
- 9 seksjoner: infra, DB, tjenester, CLI, Caddy, app-logikk,
  konvensjoner, arkitekturprinsipper, gjenoppbyggingssteg
- Selvforsynt: gitt ren server + manual = kjørende system
- Diff-modus for å se hva som har endret seg
- Secrets redacted, brukerdata ekskludert
- Daglig regenerering + ved deploy

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 12:29:22 +00:00
8e80102f6b Fullfør oppgave 22.2: Frontend-migrering fra SpacetimeDB til portvokteren
Frontend bruker nå kun portvokterens WebSocket for sanntidsdata.
SpacetimeDB-klienten er erstattet med en enkel WebSocket-klient
som kobler til /ws-endepunktet og oppdaterer reactive stores direkte.

Frontend-endringer:
- Nye lokale typer (types.ts) erstatter STDB module_bindings
- connection.svelte.ts: WebSocket til portvokteren med auto-reconnect
- stores.svelte.ts: Prosesserer WS-meldinger (initial_sync + events)
- MixerTrait: STDB-reducers erstattet med HTTP API-kall
- api.ts: Nye mixer-endepunkter (create, gain, mute, effect, role)
- +layout.svelte: Fjernet dual-tilkobling, kun portvokterens WS
- pg-ws.svelte.ts: Slettet (erstattet av connection.svelte.ts)

Dokumentasjon:
- datalaget.md: Fase M1+M2 markert som fullført
- api_grensesnitt.md: Oppdatert arkitekturdiagram, nye mixer-endepunkter
2026-03-18 12:26:33 +00:00
652d2b8917 Presiser at ↑-bump erstatter svaret in-place, ikke forlenger samtalen
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 12:24:02 +00:00
b971347dc6 Spesifiser responskvalitet: intelligens/innsats-nivåer med ↑-knapp
Ny feature-spec for synlig kvalitetsstyring av bot-svar:
- Tre nivåer intelligens (Haiku/Sonnet/Opus) og innsats (low/med/high)
- Diskret indikator (🧠●●○ 💪●○○) i svar-header
- Én ↑-knapp for "gi bedre svar" — bumper begge nivåer
- Automatisk nivåvalg fra heuristikker, bruker overstyrer med ↑
- retry_of-edge mellom erstattet og nytt svar
- Default-nivå konfigurerbart per cli_tool-node i PG

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 12:23:13 +00:00
d7a9f3816d Fullfør oppgave 22.1: WebSocket-lag med PG LISTEN/NOTIFY og frontend dual-tilkobling
Backend:
- ws.rs: Fikset WS auth via query-param (browser kan ikke sende headers ved WS upgrade)
- auth.rs: Gjort decoding_key pub for gjenbruk i ws-modulen

Frontend:
- pg-ws.svelte.ts: Ny PG WebSocket-klient med auto-reconnect og event-logging
- index.ts: Eksporterer pgWsConnect/pgWsDisconnect/pgWsState
- +layout.svelte: Kobler til PG WS i parallell med STDB for verifisering

Docs:
- api_grensesnitt.md: Dokumentert /ws endepunkt og sanntidsarkitektur
- tasks.md: Merket 22.1 som ferdig

Deploy: Krever restart av maskinrommet + rebuild av frontend.
2026-03-18 12:01:10 +00:00
b31ee59868 Ytelse: profiler PG-spørringer, optimaliser node_access-oppdatering (oppgave 12.4)
Profilert alle kritiske PG-spørringer med EXPLAIN ANALYZE.
Identifiserte at recompute_access brukte single-column index
(idx_edges_type) med lav selektivitet, og RLS-policyer manglet
composite indexes for effektive oppslag.

Endringer:

Migrasjon 017_query_performance.sql:
- 6 nye composite indexes:
  - idx_edges_target_type (target_id, edge_type) — recompute_access + belongs_to
  - idx_edges_source_type (source_id, edge_type) — alias-oppslag
  - idx_edges_target_memberof (partial, member_of) — team-propagering
  - idx_nodes_created_at_desc — ORDER BY created_at DESC
  - idx_nodes_kind_created — filtrer på kind + sorter
  - idx_na_subject_covering INCLUDE (object_id) — RLS without heap lookup
- Optimalisert recompute_access(): steg 3 og 4 kjøres nå bare
  når det er relevant (EXISTS-sjekk først). For vanlige brukere
  (ikke team) unngår dette to fulle INSERT-SELECT-operasjoner.
- via_edge oppdateres nå korrekt ved access-nivå-endring.

Slow query logging (maskinrommet):
- Forespørsler >200ms logges som WARN med tag slow_request
- PG-spørringer >100ms logges som WARN med tag slow_query
- recompute_access-kall logges med varighet for overvåking
- Nytt pg_stats-felt i /metrics med tabell- og index-statistikk,
  cache hit ratio, og node_access-telling

Dokumentasjon oppdatert i docs/infra/observerbarhet.md.
2026-03-18 11:43:19 +00:00
0fc559a207 Feilhåndtering: retry med backoff + dead letter queue for PG-skrivinger (oppgave 12.3)
Erstatter fire-and-forget tokio::spawn() i skrivestien med jobbkø-basert
persistering. Alle PG-skriveoperasjoner (insert/update/delete for noder
og edges) går nå gjennom den eksisterende jobbkøen som allerede har:

- Eksponentiell backoff (30s × 2^n) ved feil
- Dead letter queue (status='error' etter max_attempts=3)
- Admin-API for overvåking, manuell retry og avbryt
- Ressursstyring og prioritetsregler

Ny modul pg_writes.rs med:
- 5 enqueue-funksjoner (erstatter spawn_pg_*)
- 5 job-handlere for dispatch i worker-loopen
- Full paritet med gammel logikk: tilgangsgivende edges kjører
  recompute_access i transaksjon, synker til STDB, trigger rendering

Før: PG-skrivefeil logget og glemt → data kun i STDB, tapt fra PG.
Nå: automatisk retry → admin-synlig dead letter → manuell recovery.
2026-03-18 11:26:48 +00:00
81d2ece2f1 Revider datalaget: fas ut SpacetimeDB, PG LISTEN/NOTIFY + WebSocket
SpacetimeDB var et godt eksperiment, men gir synk-kompleksitet,
dobbelt vedlikehold og en ekstra SPOF for minimal latensgevinst
på denne skalaen. PG LISTEN/NOTIFY + WebSocket i portvokteren
erstatter sanntidslaget.

- datalaget.md: revidert med ny lagmodell, PG-triggers, migrasjonsplan
- retninger/README.md: oppdatert status til «Revidert»
- tasks.md: ny fase 22 (STDB-migrering) med 5 oppgaver (M1–M5)
- 12.4 oppdatert fra «profiler STDB» til «profiler PG»

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 11:15:46 +00:00
0f03886091 Backup: daglig PG-dump, STDB-krasj-recovery, helsesjekk (oppgave 12.2)
Tre ting implementert:

1. PG-dump rutine (scripts/backup-pg.sh):
   - Daglig cron kl. 03:00 UTC via /etc/cron.d/synops-backup
   - pg_dump -Fc (custom format, komprimert), konsistent uten nedetid
   - Rotasjon: beholder 30 dager, sletter eldre
   - Verifiserer at dump-filen er gyldig (ikke tom)

2. STDB → PG gjenoppbygging ved krasj (stdb_monitor.rs):
   - Bakgrunnsmonitor sjekker STDB hvert 30. sekund
   - Oppdager krasj (var oppe → nå nede)
   - Venter på at containeren restarter (maks 10 min)
   - Kjører warmup (PG → STDB) automatisk
   - Hele prosessen logges

3. Forbedret backup-helsesjekk (health.rs):
   - Sjekker /srv/synops/backup/pg/ for nyeste dump
   - Rapporterer ok/stale/missing i /admin/health
2026-03-18 11:11:32 +00:00
4d7852f466 Spesifiser robusthet: fallback-kjede, bot-nedetid, function calling
Nytt infra-dokument for robusthet og fallback:
- LLM fallback-kjede via LiteLLM (Claude → GPT-4 → lokal modell)
- Automatisk nedetid-melding til brukere ved bot-feil
- Function calling: ekstern API-bot dispatcher CLI-verktøy via
  portvokteren (structured output → generisk dispatch)
- Tilgangskontroll for bot-actions per brukerrolle
- Onboarding som statisk dispatch (null LLM-kostnad)
- PG som eneste reelle SPOF, mitigering via backup+snapshot

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 11:06:32 +00:00
0012a10373 Observerbarhet: strukturert logging, metrikker, /metrics-endepunkt (oppgave 12.1)
Legger til observerbarhetslaget i maskinrommet:

- Strukturert JSON-logging via LOG_FORMAT=json (maskinlesbart for
  log-aggregering). Default er human-readable for utvikling.
- Ny metrics-modul med in-memory request latency tracking per rute
  (count, avg, min, max, p50/p95/p99 fra siste 1000 forespørsler).
- Custom axum-middleware erstatter tower_http::TraceLayer — logger
  method, path, status og duration_ms per request, og mater
  metrikk-samleren.
- GET /metrics-endepunkt som returnerer:
  - request_latency: per-rute statistikk
  - queue_depth: pending/running/error/retry fra job_queue
  - ai_cost: aggregert fra ai_usage_log (siste time/24h/30d)
- Default loggnivå endret fra debug til info for mindre støy.
2026-03-18 11:01:36 +00:00
c9f7b8ce17 Spesifiser selvdokumenterende system: Synops dokumenterer seg selv som noder
Nytt konseptdokument: systemdokumentasjon (arkitektur, features,
CLI-verktøy, retninger) lever som noder i grafen — ikke bare
markdown-filer. Én offentlig Synops-rotnode med undersamlinger.

- Claude traverserer via synops-context, ikke fillesing
- Nye utviklere navigerer fra én rotnode i webgrensesnittet
- CLAUDE.md krymper til bootstrap-peker + fallback
- docs/-filer migreres i faser: seed → dobbeltliv → noder er kilden
- synops-snapshot genererer docs fra noder (ikke omvendt)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 10:57:21 +00:00
d532e048b1 Spesifiser nodereferanser: n:-konvensjon, tilgangsprompt, privacy-signalering
Ny feature-spec for universelle nodereferanser i Synops:
- n:<id> syntaks for å linke til enhver node fra enhver kontekst
- 🔗-knapp på alle noder for kopier-lim, n:-autocomplete i editor
- Tilgangsprompt ved linking av privat node i delt kontekst
  (del som lesbar / behold privat / del utdrag)
- Privacy-signalering: privat=🔒, delt=ren, delt+lenket=👁
- Inversert markering: privathet signaliseres, fravær=trygt

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 10:50:59 +00:00
bfc88b9a80 Jobbkø-dispatcher: spawn CLI-verktøy i stedet for inline-kode (oppgave 21.15)
Alle jobbkø-handlere i maskinrommet delegerer nå til CLI-verktøy
(Command::new("synops-X")) i stedet for å kjøre logikk inline.
Stdout → jobbresultat (JSON), stderr → feillogg, exitkode → status.

Konverterte handlere:
- tts_generate → synops-tts (beholder voice-oppslag + STDB-synk)
- suggest_edges → synops-suggest-edges (STDB-synk utelatt, topics er bakgrunnsdata)
- render_article → synops-render --render-type article
- render_index → synops-render --render-type index
- audio_process → synops-audio (beholder STDB-synk)

Allerede CLI-delegerende (uendret):
- whisper_transcribe → synops-transcribe
- agent_respond → synops-respond
- summarize_communication → synops-summarize

Fortsatt inline (mangler CLI-verktøy):
- ai_process — planlagt i fremtidig oppgave

Ny felles modul: cli_dispatch.rs med run_cli_tool() og env-helpers.
synops-tts modifisert til å inkludere media_node_id i output.
Ref: docs/retninger/unix_filosofi.md
2026-03-18 10:36:38 +00:00
bde4285c15 Spesifiser generisk dispatch: navnekonvensjon erstatter hardkodet mapping
Portvokteren dispatcher via konvensjon (synops-{job_type}) med
--payload-json. Verktøyet parser payload selv. Nytt verktøy krever
ingen rekompilering — bare binary i PATH og riktig job_type.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 10:35:37 +00:00
82c8f01c31 Utvid @bot-konvensjonen: generell samtalepartner med node-fangst
@bot er først og fremst en samtalepartner som svarer på alt.
I tillegg fanger den opp actionable innhold og oppretter noder
i bakgrunnen (bugs, ideer, features, tech-debt) med riktige
tags og mentions-edges. Brukeren ser bare chat-svaret.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 10:30:25 +00:00
23c63c2458 Implementer synops-node CLI-verktøy (oppgave 21.14)
Nytt CLI-verktøy for å hente og vise en node med alle tilkoblede edges.
Støtter rekursiv graf-traversering (--depth) og to output-formater
(markdown og JSON). Brukes av Claude og maskinrommet for å inspisere
graf-tilstand.

Features:
- Hent node med alle edges (inn og ut)
- Berik edges med peer-tittel og node_kind for lesbarhet
- --depth 0: bare noden, --depth 1: + edges (default), --depth 2+: traverser
- --format md (default) eller json
- Kompakt metadata-visning, forkortet innhold

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 10:24:43 +00:00
b6cd2b4571 Implementer synops-respond CLI-verktøy (oppgave 21.8)
Bryter ut prosesseringslogikken fra maskinrommet/src/agent.rs til
et selvstendig CLI-verktøy: synops-respond. Følger unix-filosofien
der maskinrommet orkestrerer og CLI-verktøy gjør jobben.

Ansvarsdeling:
- maskinrommet beholder: kill switch, rate limiting, loop-prevensjon,
  STDB-skriving (sanntidsvisning for frontend)
- synops-respond håndterer: kontekst-henting fra PG, prompt-bygging,
  claude CLI-kall med retry, PG-skriving (node, edges, logging)

agent.rs er nå en tynn dispatcher (~140 linjer, ned fra ~305) som
validerer sikkerhet og spawner synops-respond, likt mønsteret fra
summarize.rs sin delegering til synops-summarize.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 09:51:50 +00:00
b766f063b8 Implementer synops-rss CLI-verktøy (oppgave 21.4)
Frittstående RSS/Atom-feed generator som erstatter maskinrommet/src/rss.rs.
Følger unix-filosofien: ett verktøy per oppgave, XML til stdout.

Støtter:
- Oppslag via --collection-id (UUID) eller --slug
- RSS 2.0 og Atom 1.0 (konfigurerbart via trait-metadata eller --format)
- Podcast-enclosures via has_media-edges
- --max-items for å begrense antall elementer

Verifisert mot prod-database med Sidelinja-samlingen.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 09:24:01 +00:00
5babad9e59 Gjør StudioTrait til fullverdig BlockShell-panel med lydstudio-funksjonalitet (oppgave 20.9)
StudioTrait var en minimal liste med TraitPanel-wrapper. Nå er den et
fullverdig BlockShell-panel som følger mønsteret fra CalendarTrait (20.7)
og EditorTrait (20.8):

- Fjernet TraitPanel-wrapper, bruker egen flex-layout som fyller BlockShell
- Viser lydfiler med metadata: format-tag, varighet, størrelse, dato
- Drag-and-drop ut: lydfiler kan dras til andre paneler (editor, kalender)
- Drop-aksept: mottar lydfiler fra andre paneler via BlockReceiver
- Viser prosesserte versjoner (derived_from edges) per fil
- Responsivt med @container queries (360px, 500px) og @media fallback
- Lagt til `studio` trait i trait-katalogen i docs/primitiver/traits.md
- accessToken sendes nå fra collection page til StudioTrait

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 08:52:41 +00:00
ccc7d59b7f Gjør KanbanTrait til fullverdig BlockShell-panel med inline brett (oppgave 20.6)
KanbanTrait var tidligere bare en lenke til /board/[id]. Nå viser den
kolonner og kort direkte i BlockShell-panelet, med full funksjonalitet:

- Inline kanban-brett med kolonner (todo/in_progress/done) fra metadata
- Intern drag-and-drop mellom kolonner (status-edge oppdatering)
- Cross-panel drag: kort bruker setDragPayload for drag til andre paneler
- BlockReceiver: aksepterer drops fra chat/editor (innholdstransfer-modus)
- Opprett kort direkte i kolonne (inline input)
- Responsivt: kolonner stables vertikalt på smale paneler (@container + @media)
- accessToken-prop lagt til for mutasjoner

/board/[id]-ruten beholdes som frittstående visning.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 08:34:43 +00:00
9484f831ce Gjør ChatTrait til fullverdig BlockShell-panel med inline chat (oppgave 20.5)
ChatTrait viser nå meldinger, input og taleopptak direkte i panelet i
stedet for bare lenker til /chat/[id]. Ved flere kanaler vises kanalliste
med klikk-navigasjon; ved én kanal åpnes chatten direkte.

Endringer:
- ChatTrait: inline meldingsvisning, ChatInput, AudioPlayer, auto-scroll
- BlockReceiver peker nå til aktiv kanal (ikke bare collection)
- Meldingsbobler er draggable ut til andre paneler
- Responsivt flex-layout som tilpasser seg container-størrelse
- accessToken-prop lagt til (trengs for meldingssending)
- Forelder-sider oppdatert til å sende accessToken
- /chat/[id]-ruten beholdes som frittstående fullside-visning

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 08:28:49 +00:00
b5f47daa63 Implementer transfer service med innholdstransfer og lettvekts-triage (oppgave 20.4)
Transfer service bestemmer overføringsmodus basert på verktøy-par:
- innholdstransfer (ny node + source_material edge) for transformasjoner
  (f.eks. chat → editor: chatboble blir kilde for ny artikkel)
- lettvekts-triage (ny edge/plassering) for konteksttillegg
  (f.eks. chat → kanban: noden vises i begge kontekster)

Shift-modifier overstyrer alltid til innholdstransfer (ny node).

Endringer:
- transfer.ts: resolveTransferMode() med verktøy-par-matrise,
  executeTransfer() som kaller API for node/edge-opprettelse
- BlockShell: sender e.shiftKey til onDrop-callback
- Workspace handlePanelDrop: kobler sammen modus-resolving og API-kall
- Docs: oppdatert universell_overfoering.md med implementasjonsstatus

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 08:21:35 +00:00
5b0881d5d9 Implementer BlockReceiver i alle trait-komponenter (oppgave 20.3)
Hver trait-komponent (Chat, Kanban, Kalender, Editor, Studio) har nå
en BlockReceiver med canReceive() som sjekker kompatibilitetsmatrisen.
Inkompatible drops viser forklaring og forslag til alternativ.

Endringer:
- transfer.ts: Per-verktøy compat-sjekker (checkChatCompat, checkKanbanCompat,
  checkCalendarCompat, checkEditorCompat, checkStudioCompat) + createBlockReceiver factory
- types.ts: BlockReceiver utvidet med optional receive() + PlacementIntent type
- BlockShell.svelte: Validerer payload på faktisk drop (ikke bare drag-over)
- Alle 5 traits: Eksporterer BlockReceiver med canReceive + receive
- workspace/+page.svelte: Kobler receivers til BlockShell i spatial canvas
- Doc oppdatert til å reflektere faktisk implementasjon

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 08:12:54 +00:00
d4fc271e1e Implementer source_material edge-validering (oppgave 20.2)
Legger til maskinrommet-validering for source_material edges i både
create_edge og update_edge. Metadata må inneholde:
- context: "quoted", "summarized" eller "referenced"
- excerpt: ikke-tom streng med kildeteksten

Oppdaterer edges.md med dokumentasjon av metadata-formatet.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 08:04:02 +00:00
8bf82a78d9 Implementer message_placements (oppgave 20.1)
Plasseringsrelasjon som sporer hvor meldinger vises på tvers av
kontekster (chat, kanban, storyboard, kalender, notes). Grunnmuren
for universell overføring mellom verktøy-paneler.

Tre deler:
- PG-migrasjon 016: message_placements tabell med UNIQUE constraint
  og indekser for kontekst- og meldingsoppslag
- SpacetimeDB: MessagePlacement tabell + place_message, remove_placement,
  move_on_canvas reducers for sanntids UI-oppdatering
- Maskinrommet: STDB-klientmetoder for de tre reducerne

Avvik fra spec: FK refererer nodes(id) i stedet for messages(id) siden
meldinger er noder (node_kind = 'melding'). Spec oppdatert tilsvarende.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 07:59:07 +00:00
ad04b0fabe Fullfører oppgave 19.6: Personlig arbeidsflate
Oppdaterer tasks.md (19.6 → ferdig), dokumenterer workspace
node_kind i nodes.md og personlig arbeidsflate i arbeidsflaten.md.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 07:53:39 +00:00
3be2a57f88 Fullfører oppgave 19.1: Canvas-primitiv Svelte-komponent
Implementerer det felles canvas-underlaget som whiteboard, storyboard
og fremtidige canvas-views skal bruke. Ren Svelte 5 komponent uten
backend-avhengigheter.

Funksjoner:
- Pan/zoom kamera med CSS transforms (transform-origin: 0 0)
- Viewport culling med 200px margin for smooth scrolling
- Pointer events (unified mus + touch)
- Pinch-zoom og to-finger-pan for touch
- Snap-to-grid (toggle med G-tast eller toolbar)
- Fullskjermsmodus (fixed positioning)
- Lasso-seleksjon og shift+klikk multi-select
- Edge-pan ved drag nær kanter
- Responsivt: 44px touch targets på mobil, tilpasset toolbar
- zoomToFit() for å sentrere alle objekter
- Consumer-rendering via Svelte 5 snippets

Filer:
- frontend/src/lib/components/canvas/Canvas.svelte
- frontend/src/lib/components/canvas/types.ts
- frontend/src/lib/components/canvas/index.ts

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 07:18:29 +00:00
8b5425fb59 Fullfører oppgave 18.6: Egendefinerte AI-presets
Brukere kan nå opprette egne AI-preset-noder med custom prompt,
dele dem med samlinger/team via shared_with-edges, og redigere/slette
egne presets. Modellprofil (flash/standard) er låst — kun admin
kan oppgradere fra flash til standard.

Backend:
- POST /intentions/create_ai_preset: Oppretter custom preset med
  tvunget category=custom og model_profile=flash. Valgfri deling
  til samling i samme kall.
- update_node: Beskytter model_profile mot endring av ikke-admin.
  Forhindrer kategori-endring fra custom til standard.

Frontend:
- AiToolPanel: "+ Nytt preset"-knapp, opprett/rediger-skjema med
  tittel, prompt, retning, ikon og farge. Rediger/slett/del-knapper
  for egne custom presets. Egendefinerte presets markert med "egn."
- createAiPreset() i api.ts.

Dokumentasjon:
- ai_verktoy.md: Oppdatert fasestatus, ny § 10 om egendefinerte
  presets med API-eksempler og modellprofil-beskyttelse.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 07:11:34 +00:00
bca0ff1deb Fullfører oppgave 18.2: AI-prosessering endepunkt
POST /intentions/ai_process med source_node_id, ai_preset_id og
direction (node_to_tool / tool_to_node).

Endepunktet validerer input, sjekker at kilde-node og AI-preset
finnes, verifiserer skrivetilgang for tool_to_node-retning, og
legger en ai_process-jobb i køen.

Jobb-handleren (ai_process.rs) henter kilde-content og preset-prompt,
mapper modellprofil → LiteLLM-alias (flash → sidelinja/rutine,
standard → sidelinja/resonering), kaller AI Gateway, og logger
forbruk i både ai_usage_log og resource_usage_log.

Direction-logikk (opprett ny node vs. oppdater eksisterende)
implementeres i oppgave 18.3.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 06:24:31 +00:00
cad3f4b699 Fullfører oppgave 18.1: AI-preset node-type
Implementerer node_kind 'ai_preset' med metadata-validering og
8 standardprompter som seed-data.

Validering i maskinrommet (create_node + update_node):
- prompt (påkrevd, ikke-tom streng)
- model_profile (flash | standard)
- category (standard | custom)
- default_direction (tool_to_node | node_to_tool | both)
- icon (påkrevd, ikke-tom streng)
- color (påkrevd, hex-farge #RRGGBB)

Seed-presets: Rens tekst, Korrektør, Oppsummering, Oversett,
Skriv om for publisering, Trekk ut fakta, Forenkle, Endre tone.

8 enhetstester for valideringsfunksjonen.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 06:13:09 +00:00
ac8f8c508d Fullfører oppgave 16.7: Stemmeeffekter med robot og monster voice
Robotstemme: Ring-modulasjon via OscillatorNode som modulerer
GainNode.gain — gir metallisk, Dalek-aktig effekt. Justerbar
frekvens (30–300 Hz) og modulasjonsdybde (0–100%).

Monsterstemme: Egenutviklet AudioWorkletProcessor med phase vocoder
for sanntids pitch-shifting. Bruker overlap-add med 2048-sample FFT
og 4x overlap for ~42ms latens ved 48kHz. Pitch-faktor 0.5x–2.0x.

UI: Effektvelger-knapper (Robot/Monster) i FX-seksjon per kanal,
med fargekodede parametersliders som vises når effekten er aktiv.
On/off-state synkroniseres via STDB toggle_effect, parametere er
per-klient (ulike brukere kan ha forskjellige monitorinnstillinger).

STDB: Lagt til set_effect_param reducer for fremtidig param-synk
(krever spacetime CLI for publish — ikke deployet ennå).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 05:34:59 +00:00
171c9b991a Fullfører oppgave 16.6: EQ-effektkjede med per-kanal toggles og presets
Implementerer tre EQ-effekter i Web Audio-grafen:
- Fat bottom: BiquadFilterNode lowshelf +8dB @ 200Hz
- Sparkle: BiquadFilterNode highshelf +4dB @ 10kHz
- Exciter: WaveShaperNode (soft-clip saturation) + highshelf +4dB @ 3.5kHz
- Highpass 80Hz alltid aktiv for rumble-fjerning

Signalkjede per kanal:
  Source → Analyser → HighPass → FatBottom → Exciter → Sparkle → Gain → Master

Per-kanal toggles synkroniseres via STDB toggle_effect reducer
(allerede implementert i fase B). UI viser fargede toggle-knapper
og preset-velger (Av, Podcast-stemme, Radio-stemme).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 05:24:24 +00:00
8acb5a8731 Fullfører oppgave 16.5: Sound pads med 4×2 pad-grid
Implementerer lydpads (inspirert av RødeCaster Pro II) i mixeren:

- mixer.ts: Nytt pad-system med AudioBuffer-caching, GainNode per pad,
  og one-shot AudioBufferSourceNode-avspilling. Funksjoner for load,
  play, stop, og gain-kontroll.

- livekit.ts: Data message-støtte (sendDataMessage, onDataMessage) for
  synkronisert pad-avspilling på tvers av LiveKit-deltakere. Bruker
  reliable delivery med topic-filtrering.

- SoundPadGrid.svelte: 4×2 responsivt pad-grid med fargede knapper.
  Forhåndslaster lydfiler fra CAS til AudioBuffer. Visuell feedback
  ved avspilling (scale-animasjon). Konfigurasjonsmodus for å sette
  label, farge og laste opp lydfil per pad. Pad-konfig lagres i
  metadata.mixer.pads på samlingsnoden.

- MixerTrait.svelte: Integrerer SoundPadGrid mellom kanalstriper og
  master-seksjon. Sender isViewer-prop for tilgangskontroll.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 05:17:30 +00:00
453ec4fb59 Fullfører oppgave 16.4: Delt mixer-kontroll via SpacetimeDB
Implementerer sanntids mixer-synkronisering mellom alle deltakere i et
LiveKit-rom via SpacetimeDB. Når én deltaker justerer gain eller muter
en kanal, oppdateres alle klienters Web Audio-graf og UI umiddelbart.

SpacetimeDB-modul (Rust):
- MixerChannel-tabell med room_id/target_user_id-indekser
- Reducers: set_gain (clamped 0.0-1.5), set_mute, toggle_effect,
  create/delete_mixer_channel, set_mixer_role (editor/viewer)
- Viewer-sjekk i reducers — viewer kan ikke endre andres kanaler
- Opprydding av mixer-kanaler i close_live_room og clear_all

Frontend (SvelteKit):
- mixerChannelStore med reaktive callbacks og room_id-indeks
- MixerTrait leser delt state fra STDB, skriver endringer via reducers
- suppressRemoteSync-flagg forhindrer feedback-loop ved egne endringer
- Viewer-modus: disabled sliders/knapper for låste deltakere
- Visuell (V)-indikator for viewer-kanaler

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 05:08:23 +00:00
5771d1eed6 Fullfører oppgave 15.9: Brukersynlig forbruk
Legger til to nye API-endepunkter for brukersynlig ressursforbruk:
- GET /my/usage — brukerens eget forbruk (filtrert på triggered_by)
- GET /query/node_usage — forbruk for én node (kun eier/admin)

Frontend:
- /profile — profilside med grafstatistikk og forbruksoversikt
- NodeUsage-komponent integrert i samlings-detaljsiden
- Brukernavn i header lenker nå til profilsiden

Tilgangssjekk: nodeforbruk krever created_by eller owner/admin-edge.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 04:42:47 +00:00
d7dffa06e6 Fullfører oppgave 15.8: Forbruksoversikt i admin
Aggregert ressursforbruk-dashboard som spør mot resource_usage_log
(oppgave 15.7). Tre visninger: totaler per ressurstype, per samling,
og daglig tidsserie. AI drill-down viser forbruk per jobbtype og
modellnivå (fast/smart/deep).

Backend: GET /admin/usage med days- og collection_id-filtre.
Frontend: /admin/usage med filterbare tabeller og fargekodede kort.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 04:34:08 +00:00
eb81055ef4 Fullfører oppgave 15.7: Ressursforbruk-logging
Sentralisert logging av alle ressurskrevende operasjoner til
resource_usage_log-tabellen (opprettet i migrasjon 009).

Ny kode:
- resource_usage.rs: hjelpemodul med log() og find_collection_for_node()
- bandwidth.rs: Caddy JSON-logg-parser med nattlig batch-jobb (kl 03:00)

Logging lagt til i handlere:
- AI: summarize, ai_edges (token-telling via LiteLLM usage-felt),
  agent (placeholder — claude CLI gir ikke token-info)
- Whisper: duration_seconds, model, language, mode
- TTS: refaktorert til sentralisert modul, lagt til collection_id
- CAS: logger nye filer ved upload (ikke dedup)
- LiveKit: logger join-hendelser (faktisk deltaker-minutter
  krever webhook-integrasjon i fremtiden)

Caddy-config: JSON access logging aktivert for sidelinja.org og
synops.no i /srv/synops/config/caddy/Caddyfile (utenfor repo).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 04:24:54 +00:00
56b7df8bf8 Fullfører oppgave 15.6: Serverhelse-dashboard
Nytt admin-dashboard for sanntids serverhelse med fire hoveddeler:

1. Tjeneste-status: Parallelle helsesjekker for alle 7 tjenester
   (PG, STDB, Caddy, Authentik, LiteLLM, Whisper, LiveKit) med
   latens-måling og statusrapportering (up/down/degraded).

2. System-metrikker: CPU-load via /proc/loadavg, minne via
   /proc/meminfo, disk via statvfs, oppetid via /proc/uptime.
   Vises med progress-bars og fargekodede terskler.

3. PG-statistikk: Aktive tilkoblinger, maks-tilkoblinger,
   databasestørrelse og aktive spørringer.

4. Logg-tilgang: Filtrerbar visning av logger fra alle tjenester.
   Bruker journalctl for systemd-tjenester og docker logs for
   containere. Konfigurerbart antall linjer per tjeneste.

Backend: health.rs med tokio::join! for parallelle sjekker.
Frontend: /admin/health med auto-polling hvert 10. sekund.
Backup-sjekk rapporterer ok/stale/missing (ingen backup satt opp ennå).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 04:12:54 +00:00
b64f217637 Fullfører oppgave 15.5: Ressursstyring for jobbkø
Implementerer prioritetsregler, ressursgrenser og LiveKit-bevisst
resource governor for jobbkø-workeren, pluss disk-overvåking med varsling.

Hovedkomponenter:

1. Prioritetsregler (job_priority_rules-tabell):
   - Konfigurerbar base_priority, cpu_weight, max_concurrent per jobbtype
   - LiveKit-justering: livekit_priority_adj og block_during_livekit
   - Timeout per jobbtype
   - Admin-API for å endre regler uten restart

2. Ressurs-governor i worker-loopen:
   - Semaphore: maks 3 samtidige jobber
   - CPU-vektgrense: total vekt maks 8 (Whisper=5, render=1, etc.)
   - Per-type concurrency-grense
   - LiveKit-status sjekkes med 10s cache-TTL
   - Jobber utsettes/nedprioriteres ved aktive LiveKit-rom
   - Individuell timeout per jobb (default 600s)
   - Jobber kjøres i egne tokio-tasks (parallell dispatch)

3. Disk-overvåking:
   - Sjekker diskbruk hvert 60. sekund via statvfs
   - Terskler: 85% warning, 90% critical, 95% emergency
   - Logger til disk_status_log (siste 1000 målinger beholdes)
   - Admin-API: GET /admin/resources/disk med historikk

4. Admin-API:
   - GET /admin/resources — samlet ressursstatus
   - GET /admin/resources/disk — diskstatus med historikk
   - POST /admin/resources/update_rule — oppdater prioritetsregel

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 04:02:11 +00:00
07fa10620b Fullfører oppgave 15.3: Jobbkø-oversikt med admin-UI
Admin kan nå se, filtrere, retrye og avbryte jobber via /admin/jobs.

Backend:
- jobs.rs: list_jobs(), count_by_status(), distinct_job_types(),
  retry_job(), cancel_job() for admin-spørringer
- intentions.rs: GET /admin/jobs, POST retry_job/cancel_job handlers
- main.rs: tre nye ruter

Frontend:
- /admin/jobs: statusoppsummering med antall per status, filter på
  type/status, paginert tabell med retry/avbryt-knapper, 5s polling
- /admin: navigasjonslenke til jobbkø

Migrasjon:
- 013_job_queue.sql: formaliserer job_queue-tabellen med admin-indekser

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 03:40:56 +00:00
d8e44fe57e Fullfører oppgave 15.2: Graceful shutdown med vedlikeholdsmodus
Implementerer koordinert nedstenging der admin setter et
vedlikeholdstidspunkt, brukere ser nedtelling, og systemet
stenger ned trygt etter at aktive jobber er ferdige.

Nye filer:
- maskinrommet/src/maintenance.rs — MaintenanceState med atomiske
  flagg, shutdown-koordinator (vent på scheduled_at → blokker
  nye jobber/LiveKit → vent på kjørende jobber → exit)
- frontend/src/routes/admin/+page.svelte — admin-panel for
  vedlikehold med statusvisning og aktive sesjoner

Endringer:
- jobs.rs: sjekker maintenance.is_active() før dequeue
- intentions.rs: nye endepunkter (initiate/cancel/status), blokkerer
  join_communication under vedlikehold
- main.rs: MaintenanceState i AppState, nye ruter
- api.ts: klientfunksjoner for maintenance-API
- adminpanelet.md: dokumenterer implementerte endepunkter

Flyt: admin → GET /admin/maintenance_status (se aktive sesjoner)
→ POST /intentions/initiate_maintenance → varsel broadcast via STDB
→ frontend nedtelling → scheduled_at nådd → active=true → jobbkø
pauset + LiveKit blokkert → vent maks 5 min → process::exit(0)
→ systemd restarter maskinrommet.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 03:31:32 +00:00
1425a82cdd Fullfører oppgave 14.17: A/B-testing for presentasjonselementer
Implementerer automatisk A/B-testing for forside-varianter:

- PG-migrasjon 012: ab_events-tabell for impression/klikk-logging
  med hour_of_week (0-167) for tidspunkt-normalisering
- Variant-rotasjon: ab_select() velger tilfeldig blant testing-varianter
  ved forside-rendering, winner prioriteres, retired filtreres bort
- Impression-logging: asynkron fire-and-forget ved forside-serve
  (både cache-hit og -miss), lagres i ab_events
- Klikk-attribusjon: artikkelbesøk sjekker forside-cache for aktive
  AB-varianter og logger klikk. Eksplisitt tracking via
  GET /pub/{slug}/t/{article_id}?v={edge_id}
- Periodisk evaluator (300s intervall): z-test for proporsjoner
  (p < 0.05), minimum 100 impressions per variant, oppdaterer
  edge-metadata (ab_status, impressions, clicks, ctr)
- Redaktør-overstyring: POST /intentions/ab_override markerer
  valgt variant som winner, andre som retired (krever owner/admin)
- Auto-initialisering: maybe_start_ab_test() setter ab_status=testing
  automatisk når >1 variant av samme type opprettes

Alle 42 tester passerer inkludert 3 nye z-test-tester.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 03:13:39 +00:00
63630eb55a Fullfører oppgave 14.16: Presentasjonselementer som noder
Publisert tittel, ingress, OG-bilde og undertittel er nå egne noder
koblet til artikler via title/subtitle/summary/og_image-edges.
Rendering bruker presentasjonselementer med fallback til artikkelfelt.

Backend:
- Ny query: GET /query/presentation_elements?article_id=...
- render_article_to_cas henter presentasjonselementer via edges
- fetch_article + fetch_index_articles bruker pres.elementer
- Batch-henting for forsideartikler (én SQL-spørring)
- ArticleData utvides med subtitle + og_image
- Alle fire temaer viser subtitle og OG-bilde
- SEO og_image-tag fylles fra presentasjonselement

Frontend:
- PresentationEditor.svelte: opprett/rediger tittel, undertittel,
  ingress, OG-bilde med variantvelger (editorial/ai/social/rss)
- Integrert i PublishDialog via <details>-seksjon
- API-klient: fetchPresentationElements(), deleteNode()

Grunnlag for A/B-testing (oppgave 14.17): edge-metadata støtter
ab_status/impressions/clicks/ctr, best_of() prioriterer winner > testing.

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