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>
Fjerner TraitPanel-wrapper og erstatter med selvstendig panel-layout
som matcher KanbanTrait/CalendarTrait-mønsteret:
- Selvstendig layout som fyller BlockShell content area
- Listevisning med klikk-for-å-redigere (inline tittel + innhold)
- Source_material-edges vises som "Kilder"-sidebar i editor-visningen
- Visuell venstrekant-markering på artikler med kilder
- Opprett ny artikkel direkte fra panelet
- Container queries for responsiv tilpasning (small/medium/mobile)
- Beholder all eksisterende funksjonalitet: AI preset drops, publisering,
drag-and-drop ut av panelet
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>
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>
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>
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>
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>
BlockShell er panelrammen for arbeidsflaten — wrapper rundt hvert
verktøy-panel (trait). Gir konsistent header med tittel, fullskjerm-
og lukk-knapper, drag-handles for repositionering via header,
resize-handles på alle kanter og hjørner, og drop-sone med visuell
feedback (blå glow for kompatibel, rød for inkompatibel).
Responsivt: min/max constraints, mobil-tilpasning (stacked layout,
større touch-targets, ingen resize-handles). Bruker HTML5 drag-and-drop
API for overføring mellom paneler, pointer events for repositionering.
Filer:
- blockshell/types.ts — SizeConstraints, BlockReceiver, DropZoneState
- blockshell/BlockShell.svelte — selve wrapper-komponenten
- blockshell/index.ts — eksporter
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>
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>
Implementerer toveis drag-and-drop mellom AI-verktøypanelet og
innholdspaneler, med visuell feedback og kompatibilitetssjekking.
Nye filer:
- transfer.ts: Sentralisert transfer-tjeneste med kompatibilitetsmatrise,
DragPayload-format (application/x-synops-transfer), og
inkompatibilitets-meldinger for lyd/bilde-noder.
Endringer:
- AiToolPanel: Drop-sone bruker presetets farge (dynamisk border/bg),
viser rød sone med forklaring ved inkompatible noder (lyd/bilde),
presets er draggable ut (for tool_to_node retning).
- EditorTrait: Aksepterer AI-preset drops på innholdsnoder (tool_to_node),
viser visuell feedback (lilla=kompatibel, rød=inkompatibel),
trigger in-place revisjon via aiProcess API.
- ChatTrait: Kommunikasjonsnoder er nå draggable til AI-verktøyet.
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>
Implementerer de to retningene for AI-verktøyet:
- tool_to_node ("Penselen"): Lagrer original content som revisjon i
ny node_revisions-tabell, deretter oppdaterer noden med AI-output
i både STDB (sanntid) og PG (persistering).
- node_to_tool ("Kverna"): Oppretter ny node med AI-output, med
derived_from-edge tilbake til kildenoden og processed_by-edge
til AI-preseten. Full sporbarhet i grafen.
Ny PG-tabell: node_revisions (node_id, content, title, metadata,
revision_type, created_by, ai_preset_id, job_id).
Ref: docs/features/ai_verktoy.md § 2.2, § 6.1
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>
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>
Legger til cleanup_tmp() i CasStore som sletter orphaned .tmp-filer
eldre enn 1 time. Disse oppstår når en skriveprosess krasjer midt i
en atomisk CAS-skriveoperasjon (skriv til tmp, rename til endelig path).
Ny bakgrunnsloop start_tmp_cleanup_loop() kjører hver time og fjerner
foreldede temp-filer. Følger samme mønster som pruning- og
disk-monitor-loopene.
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>
Legger til min/max-attributter på alle tallfelter i OperationPanel
slik at nettleseren hindrer ugyldig input før det sendes til backend.
Grensene matcher backend-valideringen i audio.rs:
- silenceThreshold: -96 til 0 dB
- silenceMinMs: 1 til 60000 ms
- normTarget: -70 til 0 LUFS
- fadeInMs/fadeOutMs: 1 til 300000 ms
- compThreshold: -60 til 0 dB
- compRatio: 1 til 20 (max lagt til, min fantes allerede)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>