synops/CLAUDE.md
vegard bbbaa1e4ca Utviklingsfilosofi i CLAUDE.md — leses av alle sesjoner
Seks prinsipper inline i CLAUDE.md: forstå hvorfor, ikke hardkod
det dynamiske, én fiks ikke workarounds, preferer fjerning,
én mekanisme per problem, gjør det riktig én gang.
Utdypning i docs/retninger/kvalitetsprinsipper.md.

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

13 KiB

Synops — Claude Code Prosjektguide

Prosjektoversikt

Synops er en plattform for redaksjonelt arbeid og podcast-produksjon. Self-hosted på Hetzner VPS med full datakontroll.

Synops er plattformen. Sidelinja (podcastredaksjonen) er en tenant — en organisasjon som bruker Synops. Denne distinksjonen er bevisst: plattformkode og infrastruktur er skilt fra tenant-data og -innhold.

Arbeidsflyt

  • Standard arbeidsmodus: Start i planleggingsmodus. Lag en grundig plan, få godkjenning, deretter implementer. Jobbene er ment å kunne kjøre lenge autonomt uten input underveis.
  • Alt skjer på serveren. Claude Code kjører direkte på produksjonsserveren (/home/vegard/synops/). Rust, Node.js og Docker er tilgjengelig. Bygging, testing og deploy skjer her. Vegard kobler til via SSH/tmux.
  • Browser-testing: Claude har ikke tilgang til browser. Visuell testing gjøres av Vegard. Claude verifiserer backend (kompilering, API, DB-state).
  • Commit og push: Bruk egen vurdering. Trygt og reverserbart.
  • Deploy til produksjon: Krever alltid eksplisitt godkjenning fra Vegard.
  • Diskusjon: Forklar og diskuter før arkitekturendringer. For implementering innenfor eksisterende spec — bare kjør.
  • Defensiv skriving: Skriv planer, arbeidsstatus og mellomresultater til disk underveis (f.eks. docs/fikseliste.md eller en dedikert fil i docs/). Kontekst kan forsvinne ved planmodus-reset eller krasj. Neste instans skal kunne lese seg opp fra filene og fortsette.
  • Oppgaver: Oppgaver er noder i grafen (node_kind: 'task'). Plukkes av agenter via PG-query, ikke filer. Se docs/infra/oppgaver.md.

Dokumentasjonstre

CLAUDE.md er eneste startdokument. Oppgavelister i roten, docs under docs/:

  • docs/infra/oppgaver.md — Oppgaver som noder i grafen

  • docs/arkitektur.md — Overordnet arkitektur, lagmodell, teknologivalg

  • docs/retninger/ — Arkitektoniske teser og vedtatte retninger:

    • README.md — Oversikt og status
    • status_quo.md — Hva v1 var: ambisiøse primitiver, tradisjonell overflate
    • rom_ikke_forum.md — Opplevelse-først, to-lags-modell, administrativ opplevelse
    • universell_input.md — Tre primitiver (input, mottak, kommunikasjon), noder+edges
    • maskinrommet.md — Rust-orkestrator: fang, prosesser, lever
    • bruker_ikke_workspace.md — Noder er sentrum: brukere, team, innhold er noder. Tilgangsmatrise fra edges.
    • datalaget.md — PG(+AGE) som graf og arkiv, PG LISTEN/NOTIFY + WebSocket som sanntidslag
    • arbeidsflaten.md — Spatial canvas med verktøy-paneler, drag-and-drop, kompatibilitetsmatrise
    • unix_filosofi.md — Maskinrommet som orkestrator, arbeid i CLI-verktøy, Claude og maskinrommet deler verktøykasse
    • kvalitetsprinsipper.md — Gjør det riktig, én gang. Ikke hardkod, forstå hvorfor, én fiks ikke workarounds
  • docs/primitiver/ — Spesifikasjoner for kjerneprimitivene:

    • nodes.md — Node-skjema, node_kind, visibility, CAS-noder, eierskap
    • edges.md — Edge-skjema, typer, metadata, systemedges
    • traits.md — Trait-system: evner/funksjonalitet for samlingsnoder, katalog, pakker
    • (kommer: input, mottak, kommunikasjonsnode)
  • docs/concepts/ — Brukeropplevelser/produktområder:

    • studioet.md, møterommet.md, redaksjonen.md, podcastfabrikken.md, kunnskapsgrafen.md, valgomaten.md, den_asynkrone_gjesten.md, publisering.md, adminpanelet.md, arbeidstavlen.md, selvdokumenterende_system.md
  • docs/features/ — Tekniske byggeklosser:

    • Se individuelle filer for chat, kanban, kalender, meldingsboks, kunnskapsgraf, whiteboard, live transkripsjon, ressursforbruk, m.fl.
    • lydstudio.md — Lydredigering via FFmpeg, EDL, ikke-destruktiv prosessering
    • artikkelverktoy.md — Langform TipTap-editor, drag-and-drop mottak, source_material-edges
    • universell_overfoering.md — Drag-and-drop mellom verktøy-paneler, kompatibilitetsmatrise
  • docs/fikseliste.md — UI-bugs og forbedringer (levende jobbliste for grensesnitt)

  • docs/proposals/ — Idébank med 32+ uimplementerte forslag (se README.md)

  • docs/setup/ — Oppsett og drift:

    • produksjon.md — Steg-for-steg oppsett av Hetzner VPS fra scratch
    • lokal.md — Historisk: lokalt utviklingsmiljø (WSL2). Utdatert — all utvikling skjer nå på serveren.
    • migration_safety.md — Sjekkliste for PostgreSQL-migrasjoner (v1 workspace-RLS, trenger omskriving til node_access)
  • docs/infra/ — Infrastruktur og drift:

    • ai_gateway.md — LiteLLM som sentralisert AI-ruter (BYOK + fallback)
    • api_grensesnitt.md — Kommunikasjonskart: SvelteKit er web-API, Rust er worker
    • jobbkø.md — PostgreSQL-basert køsystem for bakgrunnsjobber
    • synkronisering.md — Historisk: PG ↔ SpacetimeDB dataflyt (arkivdokument, SpacetimeDB fjernet mars 2026)
    • claude_agent.md — Claude som chat-deltaker: arkitektur, triggere, sikkerhet
    • observerbarhet.md — Strukturert logging, metrikk-endepunkt (/metrics), AI-kostnad
    • oppgaver.md — Oppgaver som noder: prioritet, status, agent-plukking, krasj-deteksjon
  • docs/erfaringer/ — Lærdommer fra v1 (Svelte 5, Authentik). STDB-docs arkivert i arkiv/

  • reference/ — Kode fra v1 med gjenbruksverdi (Editor.svelte)

  • ops/ — Repeterbare vedlikeholdsjobber (ryddejobb, doc-audit, drift-sjekk)

Aktører

  • Vegard — serveradmin, utvikler, bruker. Kobler til via SSH/tmux.
  • Claude — AI-agent, utvikler. Kjører direkte på serveren (/home/vegard/synops/).
  • Begge har sudo + docker-tilgang på serveren.

Stack

  • Orkestrator/Backend: Rust (maskinrommet) — kjører native på hosten
  • Frontend: SvelteKit (TypeScript, PWA)
  • Sanntid: PG LISTEN/NOTIFY + WebSocket (portvokteren)
  • Database/Graf: PostgreSQL (+Apache AGE ved behov)
  • Binærlagring: CAS (content-addressable store)
  • AI: Claude Code (chat-agent), LiteLLM (AI Gateway), faster-whisper (STT)
  • Infra: Docker (tredjepart), systemd (egenutviklet), Caddy, Authentik (SSO)

Driftsmodell: hybrid native + Docker

Egenutviklet kode kjører native på hosten (systemd). Tredjepartstjenester kjører i Docker. Prinsipp: Docker for det vi ikke bygger selv, native for det vi har full kontroll over.

Native (systemd)

Tjeneste Beskrivelse Deploy
Caddy Reverse proxy + TLS sudo systemctl reload caddy (config: /srv/synops/config/caddy/Caddyfile)
maskinrommet Rust API + jobbkø cargo build --releasesudo systemctl restart maskinrommet
SvelteKit Frontend (når klar) npm run build → systemd

Maskinrommet kjører native fordi det trenger tilgang til claude CLI og hele hosten. Env-filen genereres dynamisk av scripts/maskinrommet-env.sh med Docker container-IPs.

Docker (docker-compose)

Tjeneste Begrunnelse
PostgreSQL Versjonsstyring, enkel oppgradering
Authentik Kompleks stack (server + worker + Redis)
LiteLLM Ferdig image, sjelden oppdatering
faster-whisper Modellhåndtering, ferdig image

Kommunikasjon mellom lagene

  • Caddy (native) → Docker-tjenester: via localhost-porter (Authentik:9000, Forgejo:3000)
  • Caddy (native) → native tjenester: direkte localhost (maskinrommet:3100, SvelteKit:3200)
  • Maskinrommet (host) → Docker-tjenester: via container-IP (løses dynamisk i maskinrommet-env.sh)

CLI-verktøy (tools/)

Trenger du et verktøy — lag det. Gjør det generisk, robust og stabilt, så blir det tilgjengelig for maskinrommet (jobbkø) også. Claude og maskinrommet deler verktøykasse.

  • Navnekonvensjon: synops-<verb> (f.eks. synops-transcribe, synops-render)
  • Delt lib: synops-common crate (PG-tilkobling, CAS, node/edge-typer)
  • Dokumentert i tools/README.md
  • Ref: docs/retninger/unix_filosofi.md, docs/infra/agent_api.md

Claude som chat-deltaker

  • Agent-node: d3eebc99-9c0b-4ef8-bb6d-6bb9bd380a44 (node_kind: agent)
  • Trigger: Melding i kommunikasjonsnode der Claude er member_ofagent_respond-jobb → claude -p → svar tilbake i chatten
  • Kill switch: UPDATE agent_identities SET is_active = false WHERE agent_key = 'claude-main'
  • Detaljer: Se docs/infra/claude_agent.md

Produksjonsserver

  • IP: 157.180.81.26
  • SSH: ssh vegard@157.180.81.26
  • Root-login: Deaktivert
  • Server-filer: /srv/synops/ (docker-compose.yml, .env, config/, data/)
  • Domener (synops.no er primær):
    • synops.no — Offentlig landingsside + /pub/* + /media/* (Caddy → statisk + maskinrommet)
    • ws.synops.no — Appen (SvelteKit + /api/* → maskinrommet). Krever login.
    • auth.synops.no — Authentik SSO
    • api.synops.no — Maskinrommet direkte (CLI, webhooks, eksternt)
    • git.synops.no — Forgejo (SSH port 222)
    • vegard.info — Personlig nettsted (statisk)
    • sidelinja.org — Redirect til synops.no
    • workspace.synops.no — Legacy redirect til ws.synops.no
    • *.sidelinja.org — Legacy aliaser (auth, api, git)

Git

  • Repos i Forgejo:
    • vegard/synops — plattformkode og arkitektur: ssh://git@git.synops.no:222/vegard/synops.git
    • sidelinja/sidelinja — podcastinnhold: ssh://git@git.synops.no:222/sidelinja/sidelinja.git
  • Git-identitet: vegard / vnotnes@pm.me
  • Forgejo-bruker: vegard (admin)
  • CLI: Bruk tea, ikke gh (vi bruker Forgejo, ikke GitHub)

Viktige regler

  • Aldri eksponere databaseporter mot internett
  • All AI-trafikk via maskinrommet, aldri direkte til leverandør-APIer
  • Tunge jobber (Whisper, LLM, TTS) blokkerer aldri brukerforespørsler
  • Sjekk alltid relevant doc i docs/ før implementering
  • Dokumenter lærdommer i docs/erfaringer/

Lagmodell

GUI (SvelteKit) — spatial canvas med verktøy-paneler
  │ skriv              │ les (sanntid via WebSocket)
  ▼                    ▲
Maskinrommet (Rust) ───┘ PG LISTEN/NOTIFY → WebSocket → GUI
  │ orkestrerer
  ▼
CLI-verktøy (tools/) ←── Claude bruker de samme
  │
  ▼
Tjenester: PG+AGE, CAS, Whisper, LiteLLM, LiveKit ...

Kjerneprinsipper

  1. Alt er noder og edges. Ingen separate tabeller for chat, kanban, kalender, notater. Visninger er spørringer mot grafen.
  2. Tre primitiver: Input (fanger), Mottak (presenterer), Kommunikasjon (samler folk). Alt annet er visninger og edges.
  3. Maskinrommet orkestrerer, CLI-verktøy gjør jobben. Maskinrommet eier auth, intentions, jobbkø og edge-logikk. All prosessering (transkribering, rendering, AI, lyd) skjer i CLI-verktøy som maskinrommet spawner. Claude bruker de samme verktøyene direkte. Ny funksjonalitet starter som CLI-verktøy, absorberes i orkestratoren, dokumenteres nøye. Ref: docs/retninger/unix_filosofi.md.
  4. Noder er sentrum. Brukere, team, innhold — alt er noder. Du ser dine edges. Tilgang via materialisert tilgangsmatrise.
  5. Privat er default. Input uten mottaker-edge er privat. Security by design, ikke konfigurasjon.
  6. PG er sannhetskilden. All data lever i PostgreSQL. Sanntid via PG LISTEN/NOTIFY + WebSocket i portvokteren.
  7. Alt er paneler i en arbeidsflate. Brukergrensesnittet er et spatial canvas der verktøy plasseres, sizes og arrangeres fritt. Hver feature er et panel i BlockShell. Interaksjon mellom paneler via drag-and-drop:
    • Dra ut av kontekst → ny node. Innhold som dras fra et verktøy til et annet skaper en ny node med source_material-edge tilbake.
    • Dra verktøy inn i kontekst → transformer. Et verktøy (AI, editor, studio) som mottar en node anvender sin funksjon på originalen. Ref: docs/retninger/arbeidsflaten.md, docs/features/universell_overfoering.md.

Utviklingsfilosofi

Disse prinsippene styrer hvordan vi bygger, ikke hva. Ref: docs/retninger/kvalitetsprinsipper.md for utdypning.

  1. Forstå hvorfor, ikke bare hva. Ikke sett en konfigverdi fordi det "fikser" problemet. Forstå mekanismen. Ellers vet du ikke hva som knekker når konteksten endres.
  2. Ikke hardkod det dynamiske. Hvis en verdi kan leses fra request, miljø eller database — ikke lås den i en konfigurasjonsfil. Spør: "Hva går i stykker om vi legger til et subdomain i morgen?"
  3. Én fiks, ikke to workarounds. Finn rotårsaken. To workarounds som kompenserer for hverandre er verre enn én ufikset bug.
  4. Preferer fjerning over tillegg. Kan du løse problemet ved å fjerne kode/konfig? Gjør det. Mindre = færre feil = enklere.
  5. Én mekanisme per problem. Ikke to overlappende løsninger. Det skaper forvirring om hvilken som gjør jobben.
  6. Bedre med én ting som fungerer perfekt enn ti som fungerer halvveis. Gaffatape-løsninger skaper teknisk gjeld som vokser eksponentielt. Gjør det riktig, én gang.