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

392 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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:
```jsonc
{
"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`
```bash
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:
```bash
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":
```bash
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:**
```markdown
## 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:
```bash
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
```markdown
## 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.