Commit graph

31 commits

Author SHA1 Message Date
6370b02cc7 26.7 ferdig: utgående varsler med brukerpreferanser
Vaktmesteren kan nå sende epost-varsler og WebSocket-push til brukere
via synops-notify, med respekt for brukerens preferanser.

Endringer:
- jobs.rs: send_notification jobbtype som delegerer til synops-notify CLI
- synops-notify: preferansesjekk fra metadata.preferences.notifications
  (opt-out-modell, per-kanal og per-type bryter, --skip-preferences)
- intentions.rs: POST /intentions/send_notification (admin-only)
- Dokumentasjon: docs/features/varsler.md

Preferanseskjema (i brukernodens metadata):
  preferences.notifications.email: bool (global epost-bryter)
  preferences.notifications.ws: bool (global WS-bryter)
  preferences.notifications.<type>: bool (per-type, f.eks. task_assigned)
2026-03-19 02:08:00 +00:00
a6740f82e3 26.4 ferdig: Postfix som receive-only MTA med pipe til synops-mail
Postfix installert og konfigurert som lokal MTA kun for epost-mottak.
Ingen relay, ingen utgående kø — utgående bruker msmtp/Brevo som før.

Konfigurasjon:
- virtual_mailbox_domains: synops.no, sidelinja.org, vegard.info
- Catch-all: alle adresser under domenene aksepteres
- virtual_transport → synops-pipe: pipe(8) leverer til synops-mail
- default_transport = error: blokkerer utgående SMTP
- synops-mail --receive stub: leser stdin, logger, exit 0

Verifisert: lokal SMTP-test viser at epost aksepteres, pipes til
synops-mail, og logges korrekt i /var/log/mail.log.
2026-03-19 01:32:04 +00:00
2cc389e7f5 synops-import-podcast: importer podcast fra RSS-feed (oppgave 30.6)
CLI-verktøy som parser RSS-feed, laster ned lydfiler og artwork til
CAS, og oppretter content-noder med has_media/belongs_to/og_image-edges.

Funksjoner:
- Duplikatdeteksjon via <guid> — idempotent ved gjentatt kjøring
- --dry-run for forhåndsvisning uten skriving til DB/CAS
- Metadata: tittel, beskrivelse, pubDate, duration, episode/season-nummer
- Lydfil → CAS → media-node + has_media-edge
- Artwork → CAS → media-node + og_image-edge
- publish_at satt fra pubDate i belongs_to-edge metadata
- --payload-json for jobbkø-integrasjon med maskinrommet
- JSON-output til stdout med detaljert per-episode status

Testet med The Daily (2801 episoder) og Huberman Lab (389 episoder)
i dry-run modus — parser korrekt inkl. episode-nummerering.
2026-03-19 00:06:37 +00:00
86d7002815 synops-stats CLI: podcast-nedlastingsstatistikk fra Caddy-logger (oppgave 30.3)
Nytt CLI-verktøy som parser Caddy JSON access-logger for /media/cas/*
requests og aggregerer nedlastinger per episode per dag.

IAB-compliance:
- Filtrerer 40+ kjente bot user-agents (Googlebot, scrapers, crawlers)
- Unik IP per episode per 24t-vindu (dag-basert deduplisering)

Output: JSON med episode_id, cas_hash, date, downloads, unique_listeners,
og klient-fordeling (Apple Podcasts, Spotify, Overcast, etc.)

--write oppretter podcast_download_stats-tabell i PG med UPSERT
(cas_hash + date som unik nøkkel). Beriker med episode-info fra
has_media-edges når tilgjengelig.
2026-03-18 23:30:45 +00:00
a77a6ea12f ICS-import: synops-calendar CLI for kalenderimport (oppgave 29.11)
Nytt CLI-verktøy som parser ICS-filer (RFC 5545) og oppretter
content-noder med scheduled-edges i Synops. Duplikatdeteksjon
via ICS UID i node-metadata — re-import oppdaterer eksisterende
noder i stedet for å lage duplikater.

Støtter --file/--collection-id og --payload-json for jobbkø.
Oppretter belongs_to + scheduled edges per hendelse.
2026-03-18 22:51:16 +00:00
3b6bab5092 synops-video: CLI for video-transcode, thumbnail og varighet (oppgave 29.8)
Nytt CLI-verktøy som prosesserer video fra CAS:
- Transcode til H.264/AAC MP4 med faststart (web-optimert)
- Thumbnail-generering (JPEG, 480px bred)
- Varighet-uttrekk via ffprobe

Input: --cas-hash eller --payload-json (jobbkø-modus)
Output: JSON med transcoded_hash, thumbnail_hash, duration_ms
Med --write: oppdaterer medienodens metadata i PG

Følger samme mønster som synops-audio: CAS inn/ut, --write for
DB-persistering, --payload-json for dispatch fra maskinrommet.
2026-03-18 22:25:42 +00:00
8d327423f3 synops-feed: RSS/Atom-feed abonnement med deduplisering (oppgave 29.2)
Nytt CLI-verktøy som henter og parser RSS/Atom-feeds (via feed-rs),
oppretter content-noder for nye entries med:
- metadata.source_url, feed_entry_id, original_author, published_at
- tagged-edge "feed" (selv-edge)
- belongs_to-edge til angitt samling
- Paywall-deteksjon gjenbrukt fra synops-clip

Dedupliserer på source_url — kjøring nummer to oppretter ingen duplikater.
Designet for å kjøres periodisk av maskinrommet/jobbkø (én gang per poll).
--interval lagres som metadata for orkestreringsoppsettet.

Støtter --payload-json for jobbkø-dispatch.
2026-03-18 21:16:36 +00:00
d3ecb5b279 synops-health: sjekk status for alle tjenester i stacken (oppgave 28.7)
CLI-verktøy som sjekker PG, Caddy, Maskinrommet, LiteLLM, Whisper,
LiveKit og Authentik parallelt. Output: JSON med status per tjeneste
+ samlet helsetilstand (healthy/degraded). Exit-kode 0 = alt oppe.

Gjenbruker samme mønster som maskinrommet/src/health.rs men som
frittstående verktøy — kan brukes av admin-dashboard, overvåking,
og direkte fra CLI.
2026-03-18 20:54:27 +00:00
f1e6355037 synops-backup: PG-dump + CAS-filiste + metadata-snapshot (oppgave 28.6)
Nytt Rust CLI-verktøy som erstatter scripts/backup-pg.sh:
- pg_dump -Fc via docker exec (konsistent snapshot)
- CAS-manifest: liste over alle filer med hash og størrelse
- Metadata-snapshot (JSON) med tidsstempel, modus, statistikk
- --full / --incremental / --payload-json for jobbkø
- Rotasjon av gamle dumper (30 dager, kun ved --full)

Output: strukturert JSON med backup-sti og detaljer.
2026-03-18 20:45:02 +00:00
053990d222 synops-validate: sjekk at en node matcher forventet skjema for sin node_kind (oppgave 28.5)
Nytt CLI-verktøy som henter en node fra PG og validerer:
- Basisfelter: visibility, created_by, metadata-type, kjent node_kind
- node_kind-spesifikk metadata: collection (traits), ai_preset,
  orchestration, media, communication
- Relasjonelle sjekker: person→auth_identities, agent→agent_identities

Samler alle avvik (feiler ikke på første treff). Output i markdown
eller JSON (--format). Exit-koder: 0=OK, 1=avvik, 2=feil.

Valideringsreglene speiler maskinrommet/src/intentions.rs slik at
skrivestien og valideringsverktøyet håndhever samme skjema.
2026-03-18 20:37:23 +00:00
bdb4a697f5 synops-notify: send varsel via epost, WebSocket-push, eller begge (oppgave 28.4)
Nytt CLI-verktøy som sender varsler til brukere via to kanaler:
- Email: Slår opp epost fra auth_identities, kaller synops-mail
- WebSocket: Oppretter notification-node i PG med node_access for mottaker,
  PG NOTIFY-trigger leverer via portvokteren til brukerens WS-tilkobling

Støtter --channel email|ws|both (default: ws) og --payload-json for jobbkø-dispatch.
Validerer at mottaker er person/agent. JSON-output til stdout.
2026-03-18 20:27:04 +00:00
8436f75d87 synops-ai prompt: direkte LLM-kall via LiteLLM (oppgave 28.1)
Legger til `synops-ai prompt`-subkommando for enkel prompt-inn/tekst-ut
bruk av LLM via LiteLLM gateway. Eksisterende script-generering
flyttes til `synops-ai script`-subkommando.

Prompt-modus:
- --prompt (påkrevd): bruker-prompt
- --model (valgfri): modellalias, slås opp fra ai_job_routing hvis utelatt
- --system (valgfri): systemprompt
- --job-type: for modelloppslag og logging (default: simple_prompt)
- --temperature: LLM-temperatur (default: 0.7)
- Logger tokenbruk i ai_usage_log

Seed: simple_prompt → sidelinja/rutine i ai_job_routing.
2026-03-18 19:51:44 +00:00
b096434ff6 synops-mail CLI + msmtp-oppsett (oppgave 26.2, venter SMTP-credentials)
Implementerer synops-mail --send --to <epost> --subject <emne> CLI-verktøy
for utgående epost via msmtp. Alt er ferdig og testet strukturelt:

- tools/synops-mail: Rust CLI som bygger RFC 5322-melding og sender via msmtp
- /srv/synops/config/msmtp/msmtprc: msmtp-konfig mot Hetzner-relay (587/STARTTLS)
- Installert til /usr/local/bin/synops-mail

Blokkert av: mangler SMTP-relay brukernavn/passord. Hetzner-relay
(mail.your-server.de) krever autentisering, port 25 er blokkert utgående.
Trenger credentials i msmtprc for å fullføre.
2026-03-18 19:12:14 +00:00
5dead5dac9 synops-clip: CLI for web article extraction (oppgave 25.1)
Nytt verktøy som henter og parser webartikler til ren tekst + metadata.
Bruker Mozilla Readability (via Node.js) for artikkelekstraksjon, med
Playwright som fallback for JS-rendrede sider.

Arkitektur:
- Rust CLI (clap, reqwest) håndterer HTTP-henting, paywall-deteksjon, JSON-output
- Node.js-hjelpeskript (readability.mjs) bruker @mozilla/readability + jsdom
- Playwright-script (playwright.mjs) for headless browser-fallback
- Støtter --payload-json for maskinrommet/jobbkø-integrasjon

Paywall-deteksjon basert på:
- Kort innhold (<200 tegn)
- Norske/engelske paywall-fraser i innholdet
- CSS-klasser/HTML-attributter (piano, schibsted, amedia, etc.)
- Schema.org isAccessibleForFree meta-tagg

Output: JSON med title, author, date, content, url, paywall, excerpt, source
2026-03-18 18:24:22 +00:00
45916a6f1d Fullfør oppgave 24.7: oppdater tasks.md og tools/README.md
Markerer 24.7 som ferdig. Legger synops-ai i verktøy-tabellen.
2026-03-18 17:48:11 +00:00
6496434bd3 synops-common: delt lib for alle CLI-verktøy (oppgave 21.16)
Ny crate `tools/synops-common` samler duplisert kode som var
spredt over 13 CLI-verktøy:

- db::connect() — PG-pool fra DATABASE_URL (erstatter 10+ identiske blokker)
- cas::path() — CAS-stioppslag med to-nivå hash-katalog
- cas::root() — CAS_ROOT env med default
- cas::hash_bytes() / hash_file() / store() — SHA-256 hashing og lagring
- cas::mime_to_extension() — MIME → filendelse
- logging::init() — tracing til stderr med env-filter
- types::{NodeRow, EdgeRow, NodeSummary} — delte FromRow-structs

Alle verktøy (unntatt synops-tasks som ikke bruker DB) er refaktorert
til å bruke synops-common. Alle kompilerer og tester passerer.
2026-03-18 10:51:40 +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
9fd8fc6e57 Implementer synops-feature-status CLI-verktøy (oppgave 21.13)
Nytt verktøy som samler feature-status fra fire kilder:
1. Spec-sammendrag fra docs/features/ og docs/concepts/
2. Relaterte oppgaver fra tasks.md (fuzzy-matching på nøkkel)
3. Nylige git-commits (fil-endringer + commit-meldinger)
4. Ubesvart feedback fra PG (spec-noder med discusses-edge)

DATABASE_URL er valgfri — feedback hoppes over uten tilkobling.
Prøver også /tmp/maskinrommet.env som fallback.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 10:18:43 +00:00
da2155e34e Implementer synops-tasks CLI-verktøy (oppgave 21.12)
Parser tasks.md og viser formatert oppgavestatus med filtrering
på fase (--phase N) og status (--status todo|done|blocked|inprogress|question).
Viser sammendrag med antall per status og fremdriftsbar.

Rent filbasert verktøy — ingen database nødvendig. Finner tasks.md
automatisk fra arbeidsdir eller absolutt sti.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 10:11:46 +00:00
cfec20f024 Implementer synops-search CLI-verktøy (oppgave 21.11)
Fulltekstsøk i noder via PostgreSQL tsvector/tsquery med norsk
tekstkonfigurasjon. Bruker eksisterende GIN-indeks fra migrasjon 011.
Støtter --kind-filter og --limit. Output: markdown med relevans-score
og utdrag (ts_headline med «»-markering).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 10:08:51 +00:00
b0faa6cf60 Implementer synops-context CLI-verktøy (oppgave 21.10)
Nytt verktøy som samler kontekst for en kommunikasjonsnode i
markdown-format — deltakere, spesifikasjon (discusses-edge),
meldingshistorikk og relaterte noder. Brukes av synops-respond
og andre verktøy som trenger samtalekontekst.

Input: --communication-id <uuid> [--max-messages N]
Output: markdown til stdout

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 10:03:56 +00:00
45efeb080a Implementer synops-prune CLI-verktøy (oppgave 21.9)
Erstatter maskinrommet/src/pruning.rs med selvstendig CLI-verktøy
som følger unix-filosofien. Tre-fase pruning:

- Fase 1 (disk ≥85%): Slett regenererbart innhold (TTS, thumbnails)
- Fase 2 (alltid): TTL-basert pruning per modalitet (lyd 30d, bilde 30d, video 14d)
- Fase 3 (disk ≥95%): Kritisk — alt uten publishing-edge slettes

Dry-run er default (krever --write for faktisk sletting).
JSON-output til stdout, logging til stderr.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 09:58:03 +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
9032ab0225 Implementer synops-suggest-edges CLI-verktøy (oppgave 21.7)
Erstatter maskinrommet/src/ai_edges.rs med et selvstendig CLI-verktøy
som følger unix-filosofien: maskinrommet orkestrerer, verktøy gjør jobben.

Verktøyet analyserer en nodes innhold via LiteLLM og foreslår
topics og mentions (entiteter) som edges. I lesemodus (default)
returneres kun forslag som JSON med confidence-score. Med --write
opprettes topic-noder og mentions-edges i PG.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 09:43:03 +00:00
08ff14028b Implementer synops-summarize CLI-verktøy (oppgave 21.6)
Ekstraherer AI-oppsummeringslogikk fra maskinrommet til standalone
CLI-verktøy, i tråd med unix_filosofi.md-prinsippet om at maskinrommet
orkestrerer og CLI-verktøy gjør jobben.

synops-summarize:
- Henter meldinger og deltakere fra kommunikasjonsnode i PG
- Sender samtalelogg til LiteLLM for oppsummering
- Med --write: oppretter sammendrag-node, belongs_to/summary-edges,
  logger AI-ressursforbruk
- Uten --write: dry-run som skriver JSON til stdout

maskinrommet/src/summarize.rs er nå en tynn dispatcher som spawner
synops-summarize med --write, tilsvarende transcribe.rs-mønsteret.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 09:36:51 +00:00
1dcecc2a04 Implementer synops-tts CLI-verktøy (oppgave 21.5)
Nytt CLI-verktøy som erstatter maskinrommet/src/tts.rs.
Kaller ElevenLabs API, lagrer generert lyd i CAS, og returnerer
CAS-hash som JSON. Med --write opprettes media-node og has_media-edge
i PostgreSQL, inkludert ressurslogging.

Følger samme mønster som synops-transcribe: clap-args, tracing til
stderr, JSON til stdout, atomisk CAS-lagring via temp+rename.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 09:29:12 +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
17e35b2644 Implementer synops-render CLI-verktøy (oppgave 21.3)
Nytt CLI-verktøy som rendrer artikler og forsider til HTML via
Tera-templates og lagrer resultatet i CAS. Erstatter rendering-logikken
i maskinrommet/src/publishing.rs som standalone verktøy.

Støtter to render-typer:
- article: Rendrer enkeltartikkel med SEO-metadata, presentasjonselementer,
  TipTap→HTML-konvertering, og tema-basert CSS.
- index: Rendrer forside med hero/featured/stream-artikler.

Fire innebygde temaer: avis, magasin, blogg, tidsskrift.
Templates er kopiert fra maskinrommet og innebygd via include_str!().
TipTap-modulen er duplisert inntil synops-common (21.16) samler felles kode.

Følger eksisterende CLI-mønster: --write gater DB-oppdateringer,
JSON til stdout, stderr for logging.

16 enhetstester dekker CSS-variabler, SEO, kategorisering, rendering
og TipTap-konvertering. Verifisert mot produksjons-DB.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 09:19:02 +00:00
34b086d046 Implementer synops-audio CLI-verktøy (oppgave 21.2)
Erstatter maskinrommet/src/audio.rs med frittstående CLI-verktøy
som følger unix_filosofi-mønsteret fra synops-transcribe.

Input: --cas-hash <hash> --edl <json>
Output: JSON med ny CAS-hash til stdout

Inkluderer:
- Fullstendig parametervalidering (NaN/Inf, grenseverdier)
- FFmpeg filtergraf i riktig rekkefølge (cuts→NR→EQ→comp→norm→fades)
- To-pass loudnorm for høykvalitets normalisering
- Silence detection → cut-konvertering med 200ms margin
- Atomisk CAS-lagring via temp-fil + rename
- --write flagg for DB-operasjoner (node + edge + ressurslogg)
- 21 enhetstester for validering, filtergraf og CAS-stier

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 09:09:02 +00:00
bd12bed77e Implementer synops-transcribe CLI-verktøy (oppgave 21.1)
Bryter ut Whisper-transkribering fra maskinrommet til selvstendig
CLI-verktøy i tools/synops-transcribe/, i tråd med unix-filosofien.

Verktøyet:
- Leser lydfil fra CAS, sender til faster-whisper API (SRT-format)
- Parser SRT til segmenter, skriver JSON til stdout
- Med --write: skriver segmenter til PG, oppdaterer node metadata,
  logger ressursforbruk
- Støtter --cas-hash, --model, --initial-prompt, --language, --mime,
  --node-id, --requested-by

Maskinrommet sin transcribe.rs er nå en tynn dispatcher som spawner
synops-transcribe som subprosess med riktige env-variabler.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 09:01:06 +00:00
54c8d411e8 Legg til tools/ for Claude CLI-verktøy, dokumenter i CLAUDE.md 2026-03-18 01:44:57 +00:00