Etter vellykket pipeline-utførelse sjekker handle_orchestrate() om
orkestreringen har utgående triggers-edges til andre orchestration-noder.
Hvert gyldig mål enqueues som ny orchestrate-jobb med kaskade-kontekst.
Syklusdeteksjon via cascade_chain i jobb-payload:
- Sporer alle orchestration-IDer allerede utført i kjeden
- Blokkerer target som allerede finnes i kjeden (direkte + indirekte syklus)
- Dybdegrense på 10 ledd (MAX_CASCADE_DEPTH)
- Blokkerte kaskader logges i orchestration_log med status=skipped
Nedstrøms orkestreringer mottar:
- trigger_event: "cascade"
- upstream_orchestration_id i trigger_context
- {event.upstream_orchestration_id} tilgjengelig i script
Kaskade-feil er ikke-fatale — selve orkestreringen rapporteres som suksess.
8 nye enhetstester for syklusdeteksjon og dybdegrense.
138 lines
5.3 KiB
Markdown
138 lines
5.3 KiB
Markdown
# Edges — spesifikasjon
|
|
|
|
**Status: Besluttet.**
|
|
|
|
> Edges er relasjoner mellom noder. De er retningsbestemte, typede med
|
|
> freeform strenger, og kan bære metadata. Hva en node "er" bestemmes
|
|
> av dens edges, ikke av noden selv.
|
|
|
|
## Skjema
|
|
|
|
```sql
|
|
CREATE TABLE edges (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
source_id UUID NOT NULL REFERENCES nodes(id) ON DELETE CASCADE,
|
|
target_id UUID NOT NULL REFERENCES nodes(id) ON DELETE CASCADE,
|
|
edge_type TEXT NOT NULL,
|
|
metadata JSONB NOT NULL DEFAULT '{}',
|
|
system BOOLEAN NOT NULL DEFAULT false,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
created_by UUID REFERENCES nodes(id),
|
|
|
|
UNIQUE (source_id, target_id, edge_type)
|
|
);
|
|
|
|
CREATE INDEX idx_edges_source ON edges (source_id);
|
|
CREATE INDEX idx_edges_target ON edges (target_id);
|
|
CREATE INDEX idx_edges_type ON edges (edge_type);
|
|
```
|
|
|
|
## Retning
|
|
|
|
Edges er retningsbestemte: `source_id → target_id`. "Vegard eier
|
|
Sidelinja" er en annen edge enn "Sidelinja eier Vegard" (som ikke
|
|
gir mening). Retningen leses naturlig:
|
|
|
|
```
|
|
Vegard ──owner──→ Sidelinja (Vegard eier Sidelinja)
|
|
Referat ──belongs_to──→ Møte (referatet tilhører møtet)
|
|
Episode ──mentions──→ Jonas Gahr Støre (episoden nevner ham)
|
|
```
|
|
|
|
Symmetriske relasjoner (f.eks. vennskap) modelleres som to edges
|
|
eller som en edge-type maskinrommet vet er symmetrisk.
|
|
|
|
## Edge-typer
|
|
|
|
Freeform strenger med konvensjoner — ikke en hard enum. Nye
|
|
relasjonstyper krever ingen migrering. Systemkritiske typer
|
|
valideres i maskinrommet.
|
|
|
|
### Kjente edge-typer
|
|
|
|
| Type | Betydning | Metadata |
|
|
|------|-----------|----------|
|
|
| `owner` | Eier noden | — |
|
|
| `admin` | Administrerer noden | — |
|
|
| `member_of` | Er medlem av | — |
|
|
| `reader` | Kan kun lese | — |
|
|
| `belongs_to` | Tilhører (innhold → samling) | `{ "slot": "hero"/"featured"/null, "slot_order": 1, "pinned": true, "publish_at": "..." }` |
|
|
| `alias` | Identitet (systemedge) | `system: true` |
|
|
| `mentions` | Refererer til | — |
|
|
| `reply_to` | Svar på | — |
|
|
| `scheduled` | Tidsplanlagt | `{ "at": "2026-03-20T14:00Z" }` |
|
|
| `status` | Tilstand | `{ "value": "done" }` |
|
|
| `tagged` | Merket med | `{ "tag": "urgent" }` |
|
|
| `host_of` | Vert i | — |
|
|
| `has_media` | Har mediefil (innhold → CAS-node) | — |
|
|
| `intended_for` | Ment for publisering i (arbeidsfase) | — |
|
|
| `submitted_to` | Innsendt til redaksjonell vurdering | `{ "status": "pending", "submitted_at": "ISO8601" }` |
|
|
| `title` | Publisert overskrift (presentasjonsnode → innhold) | `{ "variant": "editorial" }` |
|
|
| `subtitle` | Undertittel | `{ "variant": "editorial" }` |
|
|
| `summary` | Ingress / forhåndsvisning | `{ "variant": "ai" }` |
|
|
| `og_image` | Forsidebilde / OpenGraph-bilde (media → innhold) | `{ "variant": "editorial" }` |
|
|
| `show_notes` | Show notes for episode | `{ "variant": "ai" }` |
|
|
| `chapter` | Kapittelmarkør for episode | `{ "at": "00:05:23" }` |
|
|
| `source_material` | Kildemateriale (avledet node → kilde) | `{ "context": "quoted", "excerpt": "..." }` |
|
|
| `assigned_to` | Tildelt (work_item → person/agent) | — |
|
|
| `observes` | Overvåker (orchestration → target node) | — |
|
|
| `triggers` | Kaskade-kobling (orchestration → orchestration) | — |
|
|
| `derived_from` | Prosessert versjon av (f.eks. lydstudio-output → original) | — |
|
|
| `has_studio` | Studio-sesjon (sesjon → medienode) | — |
|
|
|
|
Listen vokser organisk. Nye typer legges til ved behov uten
|
|
skjemaendring.
|
|
|
|
## Metadata
|
|
|
|
JSONB-feltet bærer kontekstspesifikk data om relasjonen:
|
|
|
|
- `status`-edge: `{ "value": "in_progress" }`
|
|
- `scheduled`-edge: `{ "at": "2026-03-20T14:00Z" }`
|
|
- `tagged`-edge: `{ "tag": "urgent", "color": "#ff0000" }`
|
|
- `submitted_to`-edge: `{ "status": "pending", "submitted_at": "2026-03-17T10:00:00Z" }`
|
|
Status-verdier: `pending`, `in_review`, `revision_requested`, `rejected`, `approved`.
|
|
Ved tilbakemelding: `feedback`, `feedback_by`, `feedback_at`.
|
|
- `source_material`-edge: `{ "context": "quoted", "excerpt": "Den aktuelle teksten..." }`
|
|
Context-verdier: `quoted` (sitert verbatim), `summarized` (oppsummert/omskrevet),
|
|
`referenced` (referert uten sitat). Begge felt er påkrevd og valideres i maskinrommet.
|
|
|
|
Metadata er fleksibelt og spørrbart uten migrering.
|
|
|
|
## Systemedges
|
|
|
|
Edges med `system: true` er usynlige ved traversering. De
|
|
eksisterer for systemet, ikke for brukere.
|
|
|
|
Kjente systemedges:
|
|
- `alias` — identitetskobling, aldri eksponert
|
|
|
|
## Unique-constraint
|
|
|
|
`UNIQUE (source_id, target_id, edge_type)` betyr: én edge av
|
|
hver type mellom to noder. Vegard kan ha `owner`-edge *og*
|
|
`member_of`-edge til Sidelinja, men ikke to `owner`-edges.
|
|
|
|
## Hva edges gjør med noder
|
|
|
|
Edges definerer hva en node "er" — ikke noden selv:
|
|
|
|
```
|
|
Node + member_of → kanal = chatmelding
|
|
Node + belongs_to → board
|
|
+ status → "todo" = kanban-kort
|
|
Node + scheduled → tidspunkt = kalenderoppføring
|
|
Node + belongs_to → kun bruker = privat notat
|
|
Node + mentions → topic = faktoid i kunnskapsgrafen
|
|
Node uten edges = løs tanke
|
|
```
|
|
|
|
Retyping er å endre edges. Ingen datamigrasjon.
|
|
|
|
## Tilgangsmatrise-oppdatering
|
|
|
|
Når en edge med tilgangsrolle (`owner`, `admin`, `member_of`,
|
|
`reader`) opprettes eller slettes, oppdaterer maskinrommet
|
|
`node_access`-matrisen i samme transaksjon. Se
|
|
[noder er sentrum](../retninger/bruker_ikke_workspace.md)
|
|
for full spesifikasjon.
|