MeridiansMeridians

Story pipeline — events → a legible feed [Flow]

Source path: knowledge-base/diagrams/flows/story-pipeline.md

# Story pipeline — events → a legible feed `[Flow]`

Every Program task ([program-loop](../concepts/program-loop.md)) emits a canonical `DomainProgramEvent`. Turning those into an expert-forward feed is a **pure pipeline**: registry → editorial → projection → surfaces. Stories are a projection, never a second source of truth.

```mermaid
flowchart TB
    Event["**DomainProgramEvent**<br/>kind · artifactRefs · salience · summary"]
    Event --> Reg["**Registry** — STORY_KIND_REGISTRY<br/>channel · mode · queueClass · title · consequence"]

    subgraph Ed["Editorial — two layers"]
        direction TB
        Floor["**voice floor** (deterministic)<br/>every kind gets a real headline"]
        AI["**AI craft** (best-effort)<br/>verbatim quotes or dropped whole"]
        Floor --> AI
    end
    Reg --> Floor

    subgraph Proj["Projection — pure + deterministic"]
        direction TB
        Order["projectStories<br/>order: class → salience → time"]
        Dedup["dedupStoryQueue<br/>collapse echoes"]
        Readout["resolveStoryReadout<br/>sparklines · check dots · diffs"]
        Order --> Dedup --> Readout
    end
    AI --> Order

    Readout --> Surf(["Surfaces — StoryReader · Timeline · Deck<br/>+ mobile Stories bars"])
    Surf -->|"act card → stage a Directive<br/>reminder → answer in place<br/>mark-read → caught-up"| Human(["the human judges"])
```

**Invariants**

- **The registry is the single source of per-kind facts.** `STORY_KIND_REGISTRY` (exhaustive over `ProgramEventKind`) fixes each kind's channel, mode, queueClass, title eyebrow, and consequence class; `storyChannel` / `storyTitle` read from it. *Channels ≠ tasks:* 4 tasks, but **7 channels** (reminder · research · monitor · opinion · tutor · project · canon).
- **Editorial guarantees a voice.** The core floor (`VOICE_REGISTER`) means every card has a real headline at birth. The AI pass verifies quotes verbatim against source markdown and is dropped whole if nothing survives (the card keeps its floor). Only Research / Opinion / Merge get AI enrichment; Position cards carry the floor.
- **Projection is pure.** One projection + one receipt hook (`useProgramStories`) feed every surface, so ordering / filtering / read-tracking can't drift between desktop and mobile. Cards segment into **Act** (pending decisions, importance-ranked) and **Read** (the broadcast, grouped by run); read receipts are per-member and durable.

**Where it lives:** `lib/core/program/stories/` (registry · projection · dedup · readout · channels), `lib/core/program/editorial/voice-floors.ts` (floor), `lib/server/program/editorial-orchestration.ts` + `lib/engine/program/editorial.ts` (AI), `features/program/` + `shell/mobile/` (surfaces).

> **Not yet shipped:** durable ProgramJournals (audit beyond the rolling caps) and the newsletter delivery layer.
Open on GitHub

Raw Markdown source