Validering av fase 22 (SpacetimeDB-migrering) bekrefter:
1. WebSocket-sanntid fungerer:
- maskinrommet lytter på PG NOTIFY-kanaler (node_changed, edge_changed,
access_changed, mixer_channel_changed)
- Enrichment av events med fulle rader fra PG
- Broadcast via tokio::broadcast til WebSocket-klienter
- Tilgangskontroll filtrerer events per bruker
- Frontend kobler til /ws med JWT, mottar initial_sync + inkrementelle events
2. PG LISTEN/NOTIFY-triggere verifisert i database:
- 4 notify-funksjoner: notify_node_change, notify_edge_change,
notify_access_change, notify_mixer_channel_change
- 4 triggere: nodes_notify, edges_notify, node_access_notify,
mixer_channels_notify
3. Ingen STDB-rester i aktiv kode/konfig:
- maskinrommet/src/: rent
- Cargo.toml: ingen spacetimedb-avhengigheter
- docker-compose.yml: ingen spacetimedb-tjeneste
- Caddyfile: ingen spacetimedb-proxy
- Eneste funn: frontend/src/lib/spacetime/ katalognavn —
omdøpt til frontend/src/lib/realtime/ (32 filer oppdatert)
- Historiske referanser i docs/arkiv og scripts/synops.md er OK
Fikser funnet under validering:
- Gjør collection-prop valgfri i alle trait-komponenter slik at de
fungerer i personlig arbeidsflate uten collection-kontekst
- Legger til null-guards for collection.id i alle derived-blokker
og funksjoner som oppretter edges
- Fjerner microsSinceUnixEpoch-rester fra STDB-migrasjonen —
createdAt er nå et tall (Unix µs), ikke et objekt
- Retter saveTimeout-lekkasje i collection-sida: timer ryddes nå
ved navigasjon mellom samlinger
- Fikser TypeScript-feil i editorial (number vs string, uoppnåelig
'scheduled'-sammenligning), studio (bigint vs number),
RecordingTrait ($state-generics)
- Typefeil redusert fra 55 → 4 (gjenværende er pre-eksisterende
i mixer.ts/livekit.ts, ikke fase 19-20)
Validert: Canvas pan/zoom, BlockShell, layout-persistering,
snarveier, transfer service, alle panelreworks. Frontend bygger OK.
- SoundPadGrid: spor setTimeout-IDer og rydd opp ved komponent-destroy
(unngår oppdatering av tilstand etter unmount)
- Admin usage: fiks skrivefeil "1 ar" → "1 år"
- tasks.md: marker 23.7 som fullført
Fase 9 (visninger):
- graph: fiks TypeScript-feil (string|undefined → string|null)
- kanban board: les kolonner fra metadata.traits.kanban.columns
(konsistent med KanbanTrait), behold fallback til metadata.columns
- dagbok: fiks createdAt-type (number, ikke BigInt med microsSinceUnixEpoch)
Fase 10 (AI):
- summarize.rs: refaktorer til cli_dispatch helper (DRY, konsistent
med ai_edges.rs og tts.rs)
- ai_process.rs: feil tidlig hvis LITELLM_MASTER_KEY mangler
(var unwrap_or_default → tom streng → forvirrende 401)
Alle 61 maskinrommet-tester bestått, alle CLI-verktøy kompilerer.
LiteLLM kjører med riktig modellruting (rutine/resonering).
Validering av fase 3 (frontend) og fase 4 (tilgangskontroll) avdekket to bugs:
1. belongs_to-access-gap: Når en belongs_to-edge opprettes ETTER at
noen allerede har tilgang til foreldrenoden, fikk ikke barnenoden
tilgangsoppføringer i node_access-matrisen. F.eks. kunne Vegard (eier
av en kommunikasjonsnode) ikke se innhold opprettet av Claude med
belongs_to-edge til den noden.
Løsning: Ny PG-funksjon propagate_belongs_to_access() som kopierer
forelderens tilgangsrader til barnet. Kalles fra maskinrommet ved
opprettelse av belongs_to-edges (create_node m/context, create_edge,
create_communication m/context). Retroaktiv fiks for eksisterende data.
2. Mottaksflate-sortering: Brukte .microsSinceUnixEpoch (SpacetimeDB-
BigInt-arv) på vanlig number-felt, ga alltid 0n → ingen sortering.
Fikset til direkte number-sammenligning.
Verifisert: SvelteKit + maskinrommet bygger og kjører. PG-skjema, OIDC,
WebSocket/NOTIFY, RLS-policies, team-transitivitet og visibility fungerer.
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
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.
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>
CalendarTrait var tidligere en stub med lenke til /calendar-ruten.
Nå er hele kalender-UI-et innebygd direkte i panelet:
- Månedsgrid med navigasjon (forrige/neste/i dag)
- Hendelser vises som fargekodede chips i dagceller
- Drag-and-drop mellom datoer for å flytte hendelser
- Inline opprettelse av nye hendelser (tittel + valgfri tid)
- setDragPayload for å dra hendelser til andre paneler
- BlockReceiver: aksepterer content/communication-noder fra chat/kanban
- Responsivt med @container queries for små paneler
- Hendelsesliste under grid for oversikt over måneden
Følger samme mønster som ChatTrait (20.5) og KanbanTrait (20.6).
accessToken sendes nå til CalendarTrait fra collection-siden.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>
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>
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>
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>
Brukerens standard arbeidsflate med node_kind='workspace'.
Vises på /workspace når ikke koblet til en samling.
Backend:
- GET /my/workspace: finn eller opprett brukerens workspace-node
- Automatisk provisjonering ved første besøk (STDB + async PG)
- Owner-edge fra bruker til workspace
Frontend:
- /workspace rute med Canvas + BlockShell (gjenbruker spatial canvas)
- Fritt valg av verktøy-paneler fra verktøymeny
- Layout persisteres i workspace-nodens metadata via updateNode
- Tom-tilstand med verktøy-velger for nye brukere
- Responsivt: stacked tabs på mobil, spatial canvas på desktop
- Kontekst-velger i header for navigering til samlinger
Navigasjon:
- "Min flate"-knapp på mottak-siden
- "Min arbeidsflate" i ContextHeader dropdown for samlingssider
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Dobbeltklikk på panel-header toggler minimert tilstand. Minimerte
paneler viser kun header (ikon + tittel), skjuler innhold og
resize-handles. Posisjon, bredde og full høyde bevares i layout
og gjenopprettes ved nytt dobbeltklikk. Tilstanden persisteres
i edge metadata sammen med resten av workspace-layouten.
Endringer:
- PanelLayout: nytt `minimized?`-felt
- BlockShellEvents: nytt `onMinimizeChange`-event
- BlockShell: minimized-prop, dblclick-handler, minimize-knapp,
skjuler content/resize når minimert
- Workspace-side: håndterer minimize-state, oppdaterer canvas-
objekthøyde til PANEL_HEADER_HEIGHT når minimert
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Erstatter den statiske headeren på arbeidsflaten med en interaktiv
kontekst-header som lar brukeren:
- Bytte mellom samlinger via nedtrekksmeny (kontekst-velger)
- Søke blant tilgjengelige samlinger
- Se mest brukte samlinger øverst (frekvens + recency-scoring)
- Legge til nye verktøy-paneler via verktøymenyen
- Se hvilke paneler som allerede er aktive på flaten
Nye filer:
- ContextHeader.svelte: header-komponent med kontekst-velger og verktøymeny
- workspace/recency.ts: localStorage-basert frekvens/recency-tracking
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Skriver om /collection/[id] fra vertikal stack til spatial workspace:
- Desktop: trait-paneler vises som BlockShell-wrappers på Canvas med
fri pan/zoom, drag-repositionering og resize
- Mobil (<768px): tab-navigasjon med ett synlig panel om gangen
- Tre-lags layout-modell: personlig (edge metadata) > node-default
(generert fra traits) > plattform-default (grid fallback)
- Layout persisteres debounced (1s) til brukerens owner/member_of
edge metadata via updateEdge API
- Nye traits legges automatisk til eksisterende layout
- Fjernede traits filtreres ut ved resolving
Ny fil: frontend/src/lib/workspace/types.ts
- PanelLayout/WorkspaceLayout typer
- TRAIT_PANEL_INFO med default størrelse/ikon per trait
- generateDefaultLayout(): grid-arrangement fra trait-liste
- resolveLayout(): tre-lags merging med saved layout
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Svelte-komponent for AI-prosessering i arbeidsflaten:
- AiToolPanel.svelte: Viser ai_preset-noder fra STDB som velgbare
verktøy, med modell-indikator (flash/standard) og prompt-forhåndsvisning
- Drag-and-drop mottak for tekstnoder med visuell feedback
- Validerer kompatibilitet (kun content/communication-noder)
- Kaller /intentions/ai_process via ny aiProcess()-funksjon i api.ts
- Integrert i collection-siden, tilgjengelig for alle innloggede brukere
- EditorTrait: innholdsnoder er nå draggable for AI-prosessering
- Fritekst-felt for egendefinert instruksjon (backend-støtte kommer i 18.6)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tre endringer som sammen gir brukeren innsyn i FFmpeg-feil:
1. Backend: Nytt GET /query/job_status-endepunkt i queries.rs.
Frontenden pollet allerede denne URLen, men endepunktet manglet.
Returnerer status, result og error_msg fra job_queue.
2. RenderDialog: Ny error-tilstand med formatFfmpegError() som
trekker ut lesbar feilmelding fra FFmpeg stderr-dump. Viser
kort oppsummering + ekspanderbar full feilmelding via <details>.
3. Studio-side: Sender renderError til RenderDialog som errorMessage.
Toast-varselet vises kun når dialogen er lukket (unngår duplisering).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tre forbedringer i studio-siden:
1. Interval/timeout-opprydding ved navigering: Polling-interval og
timeout lagres i komponent-variabler og ryddes opp via $effect
cleanup når komponenten demonteres. Forhindrer memory leaks og
ghost-requests etter navigering bort fra studio-siden.
2. Feilmelding etter N mislykkede polling-forsøk: Etter 5 feilede
statussjekker (nettverksfeil eller HTTP-feil) vises en
feilmelding til brukeren i stedet for stille ignorering.
Timeout-feil og jobb-feil vises også i UI.
3. Metadata JSON.parse i try/catch: Hindrer at ugyldig metadata-JSON
krasjer hele studio-siden. Logger feilen og returnerer null.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Lydstudioet var kun desktop-optimalisert med fast sidebar (w-72).
Nå responsivt med to moduser:
- Desktop (lg+): Sidebar med verktøypanel til høyre, som før
- Mobil/tablet (< lg): Waveform fyller full bredde, verktøypanel
tilgjengelig via flytende knapp som åpner bottom sheet (modal).
Operation-badge på knappen viser antall aktive operasjoner.
Header: Kompaktere padding på mobil, tittel truncates, audio-info
skjules på små skjermer. min-w-0 på hovedområdet hindrer overflow.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implementerer Mixer-UI som trait-komponent for samlingssider:
- Kanalstripe per deltaker med volumslider (0–150%), VU-meter (CSS),
nød-mute-knapp (rød, tydelig) og navnelabel
- Master-seksjon med fader, VU-meter og master-mute
- Responsivt design: stacked layout på mobil, horisontal på desktop
- Animert VU-meter via requestAnimationFrame og AnalyserNode-data
- Integrert i collection-siden som 'mixer'-trait
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Installerer livekit-client og bygger grunnlaget for sanntidslyd:
- $lib/livekit.ts: LiveKit-wrapper med romtilkobling, deltakersporing,
og Web Audio-ruting. Auto-attach av <audio> er deaktivert — all lyd
rutes gjennom AudioContext med GainNode per deltaker (klar for mixer).
- api.ts: joinCommunication/leaveCommunication API-funksjoner
- RecordingTrait.svelte: UI for tilkobling, mikrofon-toggle og deltakerliste
med live speaking-indikator
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>
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>
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>
Implementerer /admin/ai med fire faner:
- Modeller & fallback: oversikt over aliaser med fallback-kjeder,
toggle aktiv/inaktiv, legg til/fjern modeller, endre prioritet
- Ruting: jobbtype → modellalias mapping med dropdown-endring
- Forbruk: aggregert tokenforbruk per samling/alias/jobbtype
- API-nøkler: viser hvilke env-variabler som er satt (aldri verdier)
Backend (maskinrommet/src/ai_admin.rs):
- GET /admin/ai — full oversikt med aliaser, providers, ruting, forbruk
- GET /admin/ai/usage — forbruk med filtre (dager, samling)
- POST-endepunkter for CRUD på aliaser, providers og ruting-regler
PG er single source of truth. API-nøkler lagres kun som env-variabler,
admin-panelet viser bare om de er satt eller mangler.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>
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>
Implementerer systemvarsler (system_announcement-noder) som vises som
banner/toast for alle aktive klienter i sanntid via SpacetimeDB.
Backend (maskinrommet):
- POST /intentions/create_announcement: oppretter varslingsnode med
validering av announcement_type (info/warning/critical), datoer
(scheduled_at, expires_at) og blocks_new_sessions. Visibility
settes automatisk til 'open' for broadcast til alle klienter.
- POST /intentions/expire_announcement: fjerner varslingsnode med
tilgangskontroll (kun eier kan slette).
Frontend:
- SystemAnnouncements.svelte: filtrerer nodeStore for aktive
system_announcement-noder, skjuler utløpte (expires_at), viser
nedtelling for planlagte hendelser (scheduled_at). Fargekoding:
rød (critical), gul (warning), blå (info). Critical kan ikke
dismisses. Oppdaterer nedtelling hvert sekund.
- Komponent lagt til i +layout.svelte for global synlighet.
- API-funksjoner (createAnnouncement, expireAnnouncement) i api.ts.
Ref: docs/concepts/adminpanelet.md § "Systemvarsler og vedlikeholdsmodus"
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Redaktør kan nå opprette en diskusjonstråd direkte fra den redaksjonelle
arbeidsflaten, knyttet til en innsendt artikkel og dens forfatter.
Backend:
- create_communication utvides med context_id som oppretter belongs_to-edge
fra kommunikasjonsnoden til kontekstnoden (artikkelen)
- editorial_board-spørringen returnerer discussion_ids per kort (kommunikasjonsnoder
med belongs_to til artikkelen)
Frontend:
- "Start samtale"-knapp på hvert redaksjonelt kort oppretter kommunikasjonsnode
med redaktør som owner og forfatter som member, og navigerer til chatten
- Eksisterende samtaler vises som lenker på kortet
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Redaktøren ser alle artikler med submitted_to-edge til samlingen,
gruppert i fire kolonner etter status. Drag-and-drop mellom kolonner
endrer status via update_edge. Siste kolonne ("Planlagt") åpner en
dialog for å sette publish_at i edge-metadata — klar for oppgave 14.12
(planlagt publisering).
Backend: GET /query/editorial_board med forfatterinfo og edge-metadata.
Frontend: /editorial/[id] med sanntidsoppdateringer via SpacetimeDB.
Lenke fra PublishingTrait når require_approval er aktivt.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Personlig publiseringsflyt for samlinger med publishing-trait der
require_approval: false. Bruker kan publisere artikler fra mottak
til samlingen, og avpublisere ved å fjerne belongs_to-edge.
Backend:
- Nytt delete_edge-endepunkt i maskinrommet med tilgangskontroll
og automatisk forside-cache-invalidering ved avpublisering
Frontend:
- PublishDialog: forhåndsvisning, slug-editor, tema-info, bekreftelse
- EditorTrait: publiser/avpubliser-knapper på innholdsnoder i
publiseringssamlinger, velger for upubliserte artikler
- deleteEdge i API-klienten
Docs:
- Oppdatert api_grensesnitt.md med delete_edge, update_edge, set_slot
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Visuell editor for redaksjonell forside-styring. Rute:
/collection/[id]/forside med tre soner (hero, featured, strøm).
- HTML5 drag-and-drop mellom hero/featured/strøm-plasser
- Pin-knapp per artikkel (forhindrer automatisk fjerning)
- Hurtigknapper for å flytte artikler mellom slots
- Forhåndsvisning via iframe av publisert forside
- Bruker POST /intentions/set_slot API fra maskinrommet
- Sanntidsdata fra SpacetimeDB (belongs_to-edges med slot-metadata)
- PublishingTrait viser nå «Rediger forside»-knapp og publisert-lenke
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Legger til et admin-panel på samlingssiden der man kan legge til/fjerne
traits fra katalogen og konfigurere per-trait-innstillinger. Endringene
sendes via updateNode til maskinrommet som validerer mot VALID_TRAITS.
- Ny updateNode-funksjon i api.ts
- Delt trait-katalog i lib/traits.ts (brukes av collection/new og TraitAdmin)
- TraitAdmin.svelte: toggle traits, rediger config-nøkler, lagre
- Integrasjon i collection/[id] med Traits-knapp i header
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ny side /collection/new med:
- 13 forhåndsdefinerte pakker (nettmagasin, podcaststudio, redaksjon osv.)
som kort-grid med ikon, beskrivelse og trait-liste
- Manuelt trait-valg med hele trait-katalogen kategorisert i 9 grupper
- Oppsummering med valgte traits og opprett-knapp
- Navigerer til /collection/[id] etter opprettelse
Knapp «Ny samling» lagt til i mottak-headeren.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Samlingsnoder med `metadata.traits` rendres nå som egne sider på
/collection/[id]. Hvert trait-navn mappes til en dedikert Svelte-komponent
som viser relevant UI. Traits uten egen komponent vises med et generisk panel.
Komponenter for 9 traits: editor, chat, kanban, podcast, publishing,
rss, calendar, recording, transcription. Mottak-siden viser traits som
pills og lenker til samlingssiden.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Backend:
- query_graph endpoint med rekursiv CTE-traversering (fokus + dybde)
- Filtrering på node_kind og edge_type, RLS-beskyttet
- Maks 200 noder, 1-3 hops dybde
Frontend:
- D3 force-directed graf på /graph med fargekodede noder
- Opprett topic-noder (node_kind='topic') direkte fra graf-visningen
- Opprett mentions-edges mellom vilkårlige noder
- Klikk for detaljer, dobbeltklikk for fokus, dra for å flytte
- Filter-legende for nodetyper og kanttyper
- Zoom, auto-fit, sidepanel med koblingsinfo
- Graf-knapp lagt til i mottaksflaten
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ny /diary-route som viser brukerens private noder — de som kun har
owner-edge og ingen delte edges til andre. Gruppert etter dato,
nyeste først, med inline oppretting av nye innlegg.
Dagbok-knapp med tellebadge lagt til i mottak-siden.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ny rute /calendar som viser alle noder med scheduled-edge i et
månedsbasert kalenderrutenett. Bruker edge-metadata { at: ISO8601 }
for tidspunkt, med T12:00:00-konvensjon for heldagshendelser.
Funksjoner:
- Månedsnavigering med «I dag»-snarvei
- Drag-and-drop for å flytte hendelser mellom datoer (updateEdge)
- Inline-oppretting med tittel og valgfritt klokkeslett
- Fargekoding etter node_kind
- Hendelsesliste under rutenett for gjeldende måned
- Kalender-lenke med hendelsesteller på mottak-siden
- Sanntid via SpacetimeDB (edgeStore.byType('scheduled'))
Arkitekturvalg: Bruker scheduled-edges direkte fra SpacetimeDB
i stedet for legacy calendar_events-tabellen. En node blir en
kalenderoppføring ved å ha en scheduled-edge — konsistent med
«hva edges gjør med noder»-prinsippet.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implementerer kanban som noder+edges uten separate tabeller:
- Board = collection-node med metadata.board og metadata.columns
- Kort = content-noder med belongs_to-edge til board
- Status via status-edge (kort→board) med metadata.value
- Posisjon via belongs_to-edge metadata.position
Backend:
- POST /intentions/update_edge — oppdater edge-type/metadata
- GET /query/board?board_id= — hent kort med status og posisjon
Frontend:
- /board/[id] route med kolonner, drag-and-drop, kortoppretting
- Sanntid via SpacetimeDB edge-subscriptions
- Board-oppretting og navigasjon fra mottak-siden
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Claude er nå en agent-node i grafen som kan delta i samtaler.
Når en bruker sender melding i en kommunikasjonsnode der Claude
er deltaker, enqueues en agent_respond-jobb som kaller claude CLI
direkte og skriver svaret tilbake til chatten.
Nye filer:
- migrations/007_agent_system.sql: agent_identities, agent_permissions, ai_usage_log
- maskinrommet/src/agent.rs: agent_respond job handler
- scripts/maskinrommet.service: systemd-tjeneste for native kjøring
- scripts/maskinrommet-env.sh: genererer env med Docker container-IPs
Endringer:
- intentions.rs: trigger agent_respond ved melding i agent-chat
- jobs.rs: dispatch agent_respond til agent-handler
- frontend chat: bot-badge (🤖) og amber-farge på agent-meldinger
- LiteLLM config: resonering-modellalias via OpenRouter
Maskinrommet kjører nå direkte på hosten (ikke i Docker) for å
ha tilgang til claude CLI. Caddy peker til host.docker.internal.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Backend:
- GET /query/segments?node_id=... — henter nyeste segmenter for en media-node
med RLS-basert tilgangssjekk via nodes-tabellen
- POST /intentions/update_segment — redigerer segmenttekst, setter edited=true
Frontend:
- TranscriptionView.svelte: universell komponent for segment-visning med
tidsstempler, avspillingsknapp per segment, og redigerbare tekstfelt
- AudioPlayer: integrert med TranscriptionView når segmenter finnes,
faller tilbake til flat tekst ellers
- Mottak og chat-sider oppdatert med nodeId/accessToken for segment-lasting
- Fikser duration_ms → sekunder-konvertering i metadata-oppslag
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Legger til AudioPlayer-komponent som spiller av lyd fra CAS-noder
med waveform-visualisering via wavesurfer.js. Komponenten viser
play/pause, tidslinje, og kan ekspandere transkripsjonen.
Chat-visningen inkluderer nå media-noder (has_media-edges) sammen
med tekstmeldinger, sortert kronologisk. Talenotater vises med
mikrofon-ikon, waveform og transkripsjon.
Mottak-siden viser også AudioPlayer for media-noder med lyd.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Legger til VoiceRecorder-komponent som bruker MediaRecorder API for
lydopptak i nettleseren. Opptaket lastes opp til CAS via eksisterende
uploadMedia-endepunkt, som automatisk trigger Whisper-transkripsjon.
Komponenten er integrert i:
- ChatInput: mikrofon-knapp mellom tekstfelt og send-knapp
- NodeEditor: mikrofon-knapp i verktøylinjen
Flyten: opptak → webm/opus blob → upload → CAS → whisper_transcribe-jobb.
Ingen backend-endringer nødvendig — hele transkripsjons-pipelinen fra
oppgave 7.2 gjenbrukes uendret.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Brukeren kan nå dra eller lime inn bilder i TipTap-editoren.
Bildet lastes opp til CAS via upload_media-endepunktet, og settes
inn som <img> med CAS-URL i metadata.document (HTML).
Endringer:
- Ny uploadMedia() og casUrl() i api.ts for multipart upload
- @tiptap/extension-image med CasImage-utvidelse (data-node-id attr)
- handleDrop/handlePaste i editor intercepter bildefiler
- Upload-status vises i editoren mens bilder lastes opp
- accessToken sendes ned til NodeEditor fra +page.svelte
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implementerer full 1:1 chat-loop:
- NewChatDialog: velg person å starte samtale med
- Fikser API-felt (participant_ids → participants) for korrekt
kommunikasjon med maskinrommets create_communication-endepunkt
- Opprett kommunikasjonsnode med to deltakere (owner + member_of)
- Dedupliserer: finner eksisterende samtale før ny opprettes
- Chat-header viser den andre deltakerens navn i 1:1-samtaler
- Testbruker-node opprettet på server for verifisering
Full loop verifisert via STDB: node + edges + melding + belongs_to
fungerer, WebSocket-subscribers ser endringer i sanntid.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>