synops/docs/concepts/arbeidstavlen.md
vegard fd0b75ee13 Orkestrering: tre nivåer (script/fritekst/drøm) + rename portvokter→vaktmester
Orkestrering restrukturert med deklarativt script som primærnivå:
- Nivå 1: eksakte CLI-kall med {event.*}-variabler, ingen AI
- Nivå 2: fritekst tolket av bot med function calling
- Nivå 3: drømmemodus — bruker skriver fritt, mangler→work_items
- Auto-eskalering: script→bot ved uventet feil

Rename portvokter→vaktmester i alle docs — bedre navn for en
tjeneste som gjør ting, ikke bare sjekker legitimasjon.

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

13 KiB
Raw Blame History

Konsept: Arbeidstavlen (Prosjektstyring)

Filsti: docs/concepts/arbeidstavlen.md

1. Konsept

Alt prosjektarbeid i Synops — oppgaver, bugs, ideer, forslag, feature-forespørsler — er noder i PostgreSQL. Én kanban-tavle organiserer arbeidet. Claude og Vegard deler samme data via CLI og web. Arbeidselementer oppstår organisk fra samtaler, manuelt input, eller systemhendelser.

2. Hvorfor

tasks.md var en pragmatisk bootstrap. Den har tre fundamentale problemer:

  1. Race conditions. Flere Claude-instanser redigerer samme fil samtidig. Endringer overskrives, status forsvinner, git-konflikter oppstår.
  2. Fragil parsing. Bash-scripts parser markdown med regex (grep -P '^\- \[~\]'). Formateringsendringer knekker parseren.
  3. Frakoblet fra grafen. Oppgaver kan ikke lenkes til samtaler, dokumenter, eller personer via edges. De lever utenfor datamodellen.

Løsningen: arbeidselementer er noder. De deltar i grafen som alt annet. De har edges til samtaler (hvor ideen kom fra), til personer (hvem som jobber), til dokumenter (hva de implementerer), og til hverandre (foreldre/barn).

3. Nodemodell

Arbeidselementer bruker node_kind: 'work_item':

work_item-node:
  title:    "Forbedre lydkvalitet ved opptak"
  content:  "Brukere rapporterer at ..."   (ren tekst, søkbar)
  metadata: {
    "size": "small",                       // small | medium | large
    "origin": "chat"                       // chat | manual | system
  }

Kategorisering via edges, ikke typer

Det finnes ingen node_kind per kategori (task, bug, idea). Distinksjonen gjøres med tagged-edges:

work_item ──tagged──→ board  { "tag": "bug" }
work_item ──tagged──→ board  { "tag": "idea" }
work_item ──tagged──→ board  { "tag": "feature" }
work_item ──tagged──→ board  { "tag": "tech-debt" }

Dette følger eksisterende filosofi: edges definerer hva en node er, ikke noden selv.

Størrelse er organisk

Ingen tvungen hierarki-klassifisering. Et element starter som small og vokser:

"Fiks fade-bug"              → small (én commit)
"Redesign lydpipeline"       → medium (noen timer)
"Redesign lydpipeline"       → large (har fått barn-items)
  ├── belongs_to: "Nytt EDL-format"
  ├── belongs_to: "FFmpeg wrapper"
  └── belongs_to: "Oppdater studio-UI"

Samme tekst-primitiv-filosofi: en node kan vokse.

4. Edge-modell

Edge-type Source → Target Metadata Betydning
belongs_to work_item → board { "position": 1.5 } Kortet tilhører tavlen
status work_item → board { "value": "neste" } Kolonneplassering
assigned_to work_item → person/agent Hvem jobber på dette
belongs_to work_item → work_item { "position": 1.0 } Deloppgave
source_material work_item → content { "context": "summarized", "excerpt": "..." } Hvor ideen kom fra
tagged work_item → board { "tag": "bug" } Kategorisering
mentions work_item → any node Relatert dokument/feature

assigned_to er en ny edge-type. Retning: work_item → person. Semantikk: "dette elementet er tildelt denne personen/agenten."

Barn-items har sin egen status-edge. Et barn kan være ferdig mens forelderen fortsatt er i arbeid.

5. Kanban-oppsettet

Tavlen er en collection-node med kanban-trait:

{
  "node_kind": "collection",
  "title": "Synops Arbeidstavle",
  "metadata": {
    "traits": {
      "kanban": {
        "columns": ["innboks", "backlog", "neste", "pågår", "review", "ferdig"]
      }
    }
  }
}

Kolonnesemantikk

Kolonne Hva Hvem styrer WIP-grense
Innboks Ubehandlede elementer fra chat og automatikk System/@bot Ingen
Backlog Vurdert, ikke prioritert. Kan være hundrevis Vegard Ingen
Neste Prioritert og klar. Claude plukker herfra Vegard ~10
Pågår Noen jobber aktivt på dette Claude/Vegard 23
Review Implementert, venter på Vegards sjekk Claude ~5
Ferdig Arkivert. Alltid søkbart System Ingen

Bevegelsesregler

Innboks → Backlog/Neste    Vegard triagerer
Backlog → Neste            Vegard prioriterer
Neste   → Pågår           Claude/Vegard starter. assigned_to-edge opprettes
Pågår   → Review          Claude ferdig. Commits refererer work_item UUID
Review  → Ferdig           Vegard bekrefter
Review  → Pågår           Vegard ber om endringer
Enhver  → Backlog          Deprioritering

Backlog-visning

Backlog trenger ikke være kanban. Hundrevis av elementer er bedre i en filtrert listevisning med søk, tags og sortering. Bare Neste → Pågår → Review → Ferdig er aktive kanban-lanes.

6. @bot-konvensjonen

@bot er Synops sin generiske markør for AI-assistanse i samtaler. Boten er først og fremst en samtalepartner — den svarer på spørsmål, forklarer, diskuterer og hjelper. I tillegg fanger den opp actionable innhold og oppretter noder i bakgrunnen.

Boten er en generell samtalepartner

@bot svarer på alt:

"Hva betyr CTR?"
  → Forklaring i chatten. Ingen node.

"Lydkvaliteten var dårlig i dag"
  → Svar + diskusjon i chatten.
  → work_item i innboks: "Undersøk lydkvalitet" + tagged "bug"

"Kan du sjekke om RSS-feeden oppdaterte seg?"
  → Kjører synops-rss, rapporterer resultat i chatten.

"Vi bør legge til kapittelmerkering"
  → Diskuterer i chatten.
  → work_item i innboks: "Kapittelmerkering i podcast" + tagged "idea"

"Forklar hvordan edge-validering fungerer"
  → Forklaring i chatten. Ingen node.

Brukeren merker bare at de får svar. Noder dukker opp i innboksen i bakgrunnen for Vegard å triagere.

To output-kanaler

  1. Chat-svar (alltid) — boten svarer i samtalen
  2. Noder (når relevant) — boten oppretter work_items, melder fra om feil, fanger opp forslag

Kanal 2 er usynlig for brukeren. De ser bare svaret.

Slik fungerer det

  1. En bruker skriver i en kommunikasjonsnode der bot-agenten er member_of.
  2. Vaktmesteren trigger agent_respond-jobb (eksisterende flow).
  3. Boten svarer i samtalen.
  4. Boten vurderer: er noe her actionable?
  5. Hvis ja: oppretter riktig node-type med riktig tag.

Hva fanges opp?

Innhold Resultat Tag
Bug / feil / noe virker ikke work_item + mentions berørt cli_tool bug
Idé / forslag / "vi bør" work_item idea
Feature-forespørsel work_item feature
Teknisk gjeld / "dette er rotete" work_item tech-debt
Generelt spørsmål Bare chat-svar, ingen node

Hva opprettes?

For hvert actionable element:

  • work_item-node med tittel og beskrivelse
  • belongs_to-edge → arbeidstavlen
  • status-edge med value: "innboks"
  • source_material-edge → chat-meldingen (proveniens)
  • tagged-edge med riktig kategori
  • mentions-edges til berørte noder (verktøy, features)
  • Eventuelt assigned_to-edge til agent-noden (om boten kan gjøre det selv)

Vegard triagerer innboksen og prioriterer.

Ruting

@bot rutes av vaktmesteren basert på kontekst:

  • Standard: Claude (nåværende agent_respond-flyt)
  • Fremtidig: spesialiserte agenter, andre modeller, eller regelbaserte svar — uten endring i brukergrensesnittet

7. Task runner og jobbhenting

CLI: synops-tasks

synops-tasks --list [--status <status>] [--tag <tag>]
synops-tasks --next                     # neste fra "neste"-kolonnen
synops-tasks --claim <uuid> --write     # atomisk: status → pågår + assigned_to
synops-tasks --complete <uuid> --write  # status → review
synops-tasks --prompt <uuid>            # generer prompt for autonom sesjon

--claim bruker SELECT ... FOR UPDATE for atomisk status- endring. Ingen race conditions.

Task runner

run-next-task.sh blir en tynn wrapper:

TASK_JSON=$(synops-tasks --next --format json)
TASK_ID=$(echo "$TASK_JSON" | jq -r '.id')
synops-tasks --claim "$TASK_ID" --write
claude -p --dangerously-skip-permissions \
  "$(synops-tasks --prompt "$TASK_ID")"
synops-tasks --complete "$TASK_ID" --write

Stale-deteksjon

Items som har stått i "pågår" lenger enn 60 minutter uten commit frigjøres tilbake til "neste":

synops-tasks --unstale --write

8. CLAUDE.md som bootstrap

CLAUDE.md forblir prosjektets startdokument — det lastes alltid inn i konteksten. Strukturen beholdes i hovedsak, men oppgavehenting endres:

Erstatt tasks.md-referanser med:

## Arbeidshenting
Oppgaver hentes fra arbeidstavlen (PG). Bruk CLI:
- `synops-tasks --next` — vis neste oppgave
- `synops-tasks --list` — vis hele tavlen
- `synops-tasks --claim <uuid> --write` — ta en oppgave
- `synops-tasks --complete <uuid> --write` — marker ferdig

Task runner: `./scripts/run-next-task.sh`
Se `docs/concepts/arbeidstavlen.md` for full spesifikasjon.

Doc-treet i CLAUDE.md beholdes — det er verdifull navigasjon. Endringen er kirurgisk: erstatt oppgaverelaterte instruksjoner.

9. Migrering fra tasks.md

Steg 1: Opprett arbeidstavle-noden

Én collection-node med kanban-trait og seks kolonner. Fast UUID som dokumenteres i CLAUDE.md.

Steg 2: Migrer gjenstående oppgaver

Script leser tasks.md, oppretter work_item-noder for gjenstående - [ ]-elementer. Ferdigstilte [x]-elementer kan migreres til "ferdig" for historikk, eller forbli i tasks.md som lesbart arkiv i git-historikken.

Fase- og avhengighetsinfo overføres til metadata og belongs_to-edges mellom relaterte items.

Steg 3: Switch task runner

run-next-task.sh bruker synops-tasks i stedet for markdown-parsing. tasks.md redigeres ikke lenger.

10. CLI og web: samme data

Terminal (Claude/Vegard)          Web (SvelteKit)
  │                                  │
  synops-tasks --list                KanbanTrait panel
  synops-tasks --claim <uuid>        Drag-and-drop kolonne
  psql → direkte SQL                 Arbeidsflaten
  │                                  │
  └──────────── PG ──────────────────┘
                 │
                 ↕ synk
                 │
           PG LISTEN/NOTIFY → WebSocket → sanntid i frontend
Grensesnitt Leser fra Skriver til
synops-tasks CLI PG direkte PG direkte
Web (KanbanTrait) WebSocket (PG) Maskinrommet → PG
synops-respond PG PG (via maskinrommet)

Ingen nytt UI trengs — arbeidstavlen er bare en collection-node med kanban-trait. Vegard ser den på arbeidsflaten ved siden av andre paneler.

11. Komponenter

Feature Rolle i Arbeidstavlen
Kanban (trait) Visuell tavle med kolonner og drag-and-drop
Chat @bot i samtaler skaper arbeidselementer
synops-tasks CLI Claude og scripts henter/oppdaterer arbeid
synops-respond Boten oppretter work_items fra chat-innsikt
Jobbkø run-next-task.sh orkestrerer autonome sesjoner

12. Utviklingsfaser

  1. Opprett arbeidstavle-noden i PG med kanban-trait og seks kolonner.
  2. Implementer synops-tasks CLI (list, next, claim, complete, prompt).
  3. Migrer gjenstående oppgaver fra tasks.md.
  4. Oppdater run-next-task.sh til å bruke synops-tasks.
  5. Utvid synops-respond til å opprette work_items fra chat.
  6. Oppdater CLAUDE.md med ny arbeidshenting-seksjon.

13. Fallback: synops-snapshot

PG nede betyr at Claude mister tilgang til verktøyoversikt, arbeidstavle og arkitektur-noder. Løsningen er en generert snapshot-fil som alltid ligger i repo:

synops-snapshot --write
  → Kobler til PG
  → Henter: cli_tool-noder, work_items (neste/pågår/review),
    arbeidstavle-status, aktive agenter
  → Skriver til docs/snapshot.md
  → Deterministisk output — ingen diff hvis ingenting endret seg

Når den kjøres

  • Automatisk: Post-hook i run-next-task.sh etter hver oppgave
  • Periodisk: Cron (hvert 5. minutt) som sikkerhetsnett
  • Manuelt: synops-snapshot --write ved behov

Hva den inneholder

  • Alle cli_tool-noder med usage og metadata
  • Arbeidstavle-status (antall per kolonne, items i neste/pågår)
  • Siste endringer (nyeste work_items)
  • Tidsstempel for når snapshot ble generert

CLAUDE.md-referanse

## Fallback-kontekst
Hvis PG er utilgjengelig, se `docs/snapshot.md` for siste kjente
tilstand. Generert av `synops-snapshot`. Ikke rediger manuelt.

Filen committes og pushes som del av normal arbeidsflyt. synops-snapshot er selv et CLI-verktøy og en cli_tool-node i grafen.

14. Avgrensning

  • Arbeidstavlen erstatter tasks.md for prosjektstyring. Den erstatter ikke docs-filer — arkitektur, retninger, feature-specs og konseptdokumenter lever fortsatt som markdown i docs/.
  • @bot er en chat-konvensjon, ikke en ny primitiv. Den bruker eksisterende member_of-edge og agent_respond-flyt.
  • Work items er noder i grafen — ikke en separat prosjektstyringsmodul. De følger alle regler for noder, edges, visibility og tilgangskontroll.