Skip to content

NarrativeBoard: Unified Diagram System for EventFlow ​

Status: DRAFT

Authors: EventFlow Team

Created: 2025-12-16


Executive Summary ​

NarrativeBoard is a proposed unified diagram system for EventFlow that combines the best aspects of BPMN (swimlanes, flow visualization), CMMN (case management, event-driven flows), and DMN (decision tables, guard visualization) into a single, cohesive visualization.

Key Features ​

  • Unified View: Replaces Lane + State + Combined diagrams with one comprehensive visualization
  • Multi-level Collapsible Regions: Scenario-level and actor-level collapse/expand
  • Test Integration: Built-in Given-When-Then visualization and coverage heatmaps
  • Simulation Mode: Step-by-step and animated replay of scenarios
  • Decision Diamonds: BPMN-style inline guard condition visualization
  • Auto-generated: Derived from .flow files with no manual editing required

Design Philosophy ​

"Your documentation tells a story. NarrativeBoard visualizes that story."

NarrativeBoard embraces EventFlow's natural language philosophy by treating diagrams as visual narratives that unfold as users interact with them.


Problem Statement ​

Current Diagram System Limitations ​

EventFlow currently offers three diagram types:

DiagramPurposeLimitation
Lane DiagramActor communicationNo state visibility
State DiagramState transitionsNo actor context
Combined DiagramBothComplex, no interactivity

Pain Points:

  1. Context Switching: Users must switch between diagram types to understand the full picture
  2. No Test Visibility: Current diagrams don't show test coverage or scenario paths
  3. Static Only: No simulation or step-through capability
  4. Information Overload: Large systems become overwhelming without collapse/expand
  5. No Guard Details: Decision logic is hidden, not visualized

User Feedback ​

"I want to see HOW the machine moves between states while also seeing WHO is involved."

"When I'm debugging, I want to step through the flow like a debugger."

"For large systems, I need to focus on one scenario at a time."


Vision: NarrativeBoard ​

NarrativeBoard is a single, interactive diagram that tells the complete story of your EventFlow system.

┌─────────────────────────────────────────────────────────────────────────────────┐
│                                                                                 │
│   ╔══════════════════════════════════════════════════════════════════════════╗  │
│   ║                      N A R R A T I V E B O A R D                         ║  │
│   ╠══════════════════════════════════════════════════════════════════════════╣  │
│   ║                                                                          ║  │
│   ║   ┌─────────────┐   ┌─────────────┐   ┌─────────────┐   ┌─────────────┐  ║  │
│   ║   │  @customer  │   │   @order    │   │  @payment   │   │ @inventory  │  ║  │
│   ║   └──────┬──────┘   └──────┬──────┘   └──────┬──────┘   └──────┬──────┘  ║  │
│   ║          │                 │                 │                 │         ║  │
│   ║   EVENTS │     STATES      │    DECISIONS    │    TESTS        │         ║  │
│   ║   ───────┼─────────────────┼─────────────────┼─────────────────┼───────  ║  │
│   ║          │                 │                 │                 │         ║  │
│   ║   ▼ Scenario: checkout [▼ COLLAPSE]                                      ║  │
│   ║   ├── Given: cart has items, customer logged in                          ║  │
│   ║   │                                                                      ║  │
│   ║   │   :checkout ────────▶ ◆ cart not empty ─────────▶ :payment_request   ║  │
│   ║   │                      │                                               ║  │
│   ║   │                      └─[#awaiting_payment]                           ║  │
│   ║   │                                                                      ║  │
│   ║   │   :payment_success ◀────────────────────────────                     ║  │
│   ║   │                      └─[#paid]─────────────▶ :reserve_stock          ║  │
│   ║   │                                                                      ║  │
│   ║   │   :stock_reserved ◀──────────────────────────────────────────        ║  │
│   ║   │                      └─[#confirmed] ✓                                ║  │
│   ║   │                                                                      ║  │
│   ║   └── Expect: order is in #confirmed ✓                                   ║  │
│   ║                                                                          ║  │
│   ╚══════════════════════════════════════════════════════════════════════════╝  │
│                                                                                 │
│   [ ◀ Prev ] [ ▶ Next ] [ ▶▶ Play ] [ ⏸ Pause ] [ Coverage: 94% ]             │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

Design Principles ​

1. Single Source of Truth ​

One diagram type that shows everything:

  • Actor lanes (WHO)
  • Event flows (WHAT happens)
  • State changes (WHERE it pauses)
  • Guard conditions (WHY it branches)
  • Test results (HOW it's verified)

2. Progressive Disclosure ​

Information is revealed progressively:

  • Level 1: Scenario overview (collapsed)
  • Level 2: Event flow within scenario (expanded scenario)
  • Level 3: Handler details (expanded event)
  • Level 4: Context changes (expanded handler)

3. Documentation-as-Code ​

NarrativeBoard is:

  • Auto-generated from .flow files
  • Read-only (no manual editing)
  • Always synchronized with source code
  • Version controlled alongside code

4. Test-First Visualization ​

Tests are not an afterthought:

  • Scenarios ARE test cases
  • Coverage is visible at a glance
  • Simulation follows test execution
  • Assertions are marked inline

5. Natural Language Alignment ​

Visual elements mirror EventFlow's natural language:

  • Events read left-to-right like sentences
  • Guards appear as decision questions
  • States are labeled descriptively
  • Actions read as natural statements

Visual Components ​

1. Actor Lanes ​

Vertical swimlanes for each actor, inspired by BPMN:

┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐
│                 │  │                 │  │                 │
│   @customer     │  │    @order       │  │   @payment      │
│                 │  │                 │  │                 │
├─────────────────┤  ├─────────────────┤  ├─────────────────┤
│        │        │  │        │        │  │        │        │
│        │        │  │        │        │  │        │        │
│        ▼        │  │        ▼        │  │        ▼        │
│                 │  │                 │  │                 │
│        │        │  │        │        │  │        │        │
│        │        │  │        │        │  │        │        │
└─────────────────┘  └─────────────────┘  └─────────────────┘

Features:

  • Actor name in header
  • Vertical timeline (time flows down)
  • Machine actors have a distinct border style
  • External actors (like @customer) have a different style
  • Collapsible: click header to hide lane

2. Event Flows ​

Horizontal arrows showing event communication:

@customer              @order                @payment
    │                     │                     │
    │    :checkout        │                     │
    ├────────────────────▶│                     │
    │                     │  :payment_request   │
    │                     ├────────────────────▶│
    │                     │                     │
    │                     │  :payment_success   │
    │                     │◀────────────────────┤
    │                     │                     │

Arrow Styles:

  • ────▶ Solid: Regular event
  • - - -▶ Dashed: Async event (emit async)
  • ═════▶ Double: API event (api)
  • Color: Blue for normal, Green for success, Red for failure

3. Decision Diamonds ​

BPMN-style diamond shapes for guard conditions:

                         │
                         ▼
                    ┌────◆────┐
                    │ ? cart  │
                    │not empty│
                    └────┬────┘
              ┌──────────┴──────────┐
              │ true                │ false
              ▼                     ▼
        ┌──────────┐          ┌──────────┐
        │ checkout │          │  :error  │
        └──────────┘          └──────────┘

Diamond Features:

  • ◆ symbol marks the decision point
  • ? prefix shows this is a guard
  • Branches labeled with true / false or condition names
  • Multiple guards shown as nested diamonds or combined

4. State Badges ​

Inline state indicators on the timeline:

    │
    │ :checkout
    ├────────────────▶
    │
    │  ┌────────────────────┐
    │  │ #awaiting_payment  │ ← State badge
    │  └────────────────────┘
    │
    │ :payment_success
    │◀────────────────
    │
    │  ┌───────────┐
    │  │   #paid   │ ← State badge (green = terminal)
    │  └───────────┘

Badge Styles:

  • [#state] Yellow background: Waiting state
  • [#state] Green background: Terminal success state
  • [#state] Red background: Terminal failure state
  • [#state] Gray border: Initial state

5. Test Markers ​

Pass/fail indicators for assertions:

┌── scenario: successful checkout ────────────────────────────┐
│                                                             │
│   given:                                                    │
│     ✓ @customer is logged in                                │
│     ✓ cart has items                                        │
│                                                             │
│   :checkout ─────▶ ◆ ─────▶ :payment_request                │
│                                                             │
│   expect:                                                   │
│     ✓ order is in #awaiting_payment                         │
│                                                             │
│   :payment_success ◀────                                    │
│                                                             │
│   expect:                                                   │
│     ✓ order is in #paid                                     │
│     ✓ @customer received :confirmation                      │
│                                                             │
└─────────────────────────────────────────────────── PASS ✓ ──┘

Marker Styles:

  • ✓ Green checkmark: Assertion passed
  • ✗ Red X: Assertion failed
  • ○ Gray circle: Not yet executed (during simulation)
  • ⏸ Orange pause: Breakpoint

6. Wait Point Indicators ​

Highlighting where the system pauses for external input:

    │
    │ emit :payment_request to @payment
    ├─────────────────────────────────▶
    │
    │  ╔═══════════════════════════════╗
    │  ║   ⏳ WAIT POINT               ║
    │  ║   waiting for:                ║
    │  ║   • :payment_success          ║
    │  ║   • :payment_failed           ║
    │  ╚═══════════════════════════════╝
    │
    │ :payment_success
    │◀─────────────────────────────────

7. Context Panel ​

Side panel showing variable changes:

┌─────────────────────────────────────────────────────────────┐
│ CONTEXT CHANGES                                             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│ After :checkout:                                            │
│   $order_id: "ord-12345"  (new)                             │
│   $total: 1225            (unchanged)                       │
│                                                             │
│ After :payment_success:                                     │
│   $paid_at: "2025-12-16T10:30:00Z"  (new)                   │
│   $transaction_id: "txn-67890"      (new)                   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Collapsible Regions ​

Multi-Level Hierarchy ​

NarrativeBoard supports three levels of collapsing:

▼ machine: @order                          [LEVEL 1: Machine]
│
├── ▼ scenario: checkout                   [LEVEL 2: Scenario]
│   │
│   ├── given: cart has items
│   │
│   ├── ▶ on :checkout (api)               [LEVEL 3: Event - collapsed]
│   │
│   ├── ▼ on :payment_success              [LEVEL 3: Event - expanded]
│   │   │
│   │   ├── order moves to #paid
│   │   ├── $paid_at becomes now
│   │   └── emit :confirmation to @customer
│   │
│   └── expect: order is in #paid
│
├── ▶ scenario: checkout with empty cart   [LEVEL 2: Collapsed]
│
└── ▶ scenario: payment failure            [LEVEL 2: Collapsed]

Scenario-Level Collapse ​

Click scenario header to expand/collapse:

▶ scenario: successful checkout [3 events, 4 assertions] ✓
  └── Click to expand...

▼ scenario: successful checkout [3 events, 4 assertions] ✓
  ├── given: @customer is logged in, cart has items
  │
  ├── :checkout ─────▶ ◆ ─────▶ :payment_request
  │                    └─[#awaiting_payment]
  │
  ├── :payment_success ◀────
  │                    └─[#paid]
  │
  └── expect: ✓ order is in #paid

Actor-Level Collapse ​

Hide/show specific actor lanes:

┌──────────────┐  ┌──────────────┐  ┌──────────────┐
│ ☑ @customer  │  │ ☑ @order     │  │ ☐ @payment   │ ← Hidden
├──────────────┤  ├──────────────┤  └──────────────┘
│      │       │  │      │       │
│      ├───────│──│──────┤       │
│      │       │  │      │       │  Events to @payment
│      │       │  │      ├ - - - │─ shown as dotted
│      │       │  │      │       │

Keyboard Shortcuts ​

ShortcutAction
EExpand all
CCollapse all
1-9Toggle scenario N
AToggle all actors
SpaceToggle selected region

Test Integration ​

Given-When-Then Visualization ​

Each scenario is visualized as a test case:

╔═══════════════════════════════════════════════════════════════════════════════╗
║ SCENARIO: customer can checkout with valid payment                            ║
╠═══════════════════════════════════════════════════════════════════════════════╣
║                                                                               ║
║ ┌─── GIVEN ───────────────────────────────────────────────────────────────┐   ║
║ │                                                                         │   ║
║ │  ✓ @customer is logged in as "john@example.com"                         │   ║
║ │  ✓ @customer has verified payment method                                │   ║
║ │  ✓ cart contains:                                                       │   ║
║ │      | product | price |                                                │   ║
║ │      | Laptop  | 1200  |                                                │   ║
║ │      | Mouse   | 25    |                                                │   ║
║ │  ✓ $total: number is 1225                                               │   ║
║ │                                                                         │   ║
║ └─────────────────────────────────────────────────────────────────────────┘   ║
║                                                                               ║
║ ┌─── WHEN ────────────────────────────────────────────────────────────────┐   ║
║ │                                                                         │   ║
║ │  @customer        @order          @payment                              │   ║
║ │      │               │               │                                  │   ║
║ │      │  :checkout    │               │                                  │   ║
║ │      ├──────────────▶│               │                                  │   ║
║ │      │               │               │                                  │   ║
║ │      │               │◆─────────────▶│  :payment_request                │   ║
║ │      │               │               │                                  │   ║
║ │      │               │◀──────────────│  :payment_success                │   ║
║ │      │               │               │                                  │   ║
║ │      │◀──────────────│               │  :confirmation                   │   ║
║ │      │               │               │                                  │   ║
║ │                                                                         │   ║
║ └─────────────────────────────────────────────────────────────────────────┘   ║
║                                                                               ║
║ ┌─── THEN ────────────────────────────────────────────────────────────────┐   ║
║ │                                                                         │   ║
║ │  ✓ order is in #paid                                                    │   ║
║ │  ✓ @customer received :confirmation                                     │   ║
║ │  ✓ $total equals 1225                                                   │   ║
║ │                                                                         │   ║
║ └─────────────────────────────────────────────────────────────────────────┘   ║
║                                                                               ║
╚═══════════════════════════════════════════════════════════════════════════════╝
                                                                    [ PASS ✓ ]

Scenario Path Overlay ​

Multiple scenarios shown as different paths through the same diagram:

@customer              @order                @payment
    │                     │                     │
    │    :checkout        │                     │
    ├────────────────────▶│                     │
    │                     │                     │
    │                     ◆ cart not empty?     │
    │                     │                     │
    │            ┌────────┴────────┐            │
    │            │                 │            │
    │         [true]            [false]         │
    │            │                 │            │
    │            │  ═══════════════════════     │  ← Path: successful checkout
    │            │                 │            │
    │            │  - - - - - - - -│- - - - -   │  ← Path: empty cart (dashed)
    │            │                 │            │
    │            ▼                 ▼            │
    │    #awaiting_payment    :error            │
    │            │                              │

Path Legend:

  • ═══ Solid thick: Happy path (default)
  • ─── Solid thin: Alternative success path
  • --- Dashed: Error path
  • Colors: Green (pass), Red (fail), Gray (not executed)

Assertion Markers ​

Inline markers show assertion status:

expect:
  ✓ order is in #paid              │ Passed
  ✓ @customer received :confirmation│ Passed
  ✗ $total equals 1000             │ Failed: Expected 1000, got 1225
  ○ $discount applied              │ Not executed

Simulation Mode ​

Step-by-Step Navigation ​

Manual control of scenario execution:

┌─────────────────────────────────────────────────────────────────────────────┐
│                                                                             │
│   SIMULATION: checkout scenario                          Step 3 of 7       │
│                                                                             │
│   @customer              @order                @payment                     │
│       │                     │                     │                         │
│       │    :checkout        │                     │                         │
│       ├────────────────────▶│                     │   ← Step 1: Event sent  │
│       │                     │                     │                         │
│       │                     ◆ cart not empty?     │   ← Step 2: Guard       │
│       │                     │                     │                         │
│       │                     │  :payment_request   │                         │
│       │                     ├ ═══════════════════▶│   ← Step 3: CURRENT     │
│       │                     │                     │          ▲              │
│       │                     │  :payment_success   │          │              │
│       │                     │◀────────────────────┤   ← Step 4: Waiting     │
│       │                     │                     │                         │
│                                                                             │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│   [◀ Prev]  [▶ Next]  [▶▶ Auto-play]  [⏸ Pause]  [↻ Reset]                  │
│                                                                             │
│   Speed: [Slow] [Normal] [Fast]                                             │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

Animated Replay ​

Auto-play with configurable speed:

┌─────────────────────────────────────────────────────────────────────────────┐
│                                                                             │
│   ▶▶ PLAYING: checkout scenario                         [⏸ Click to pause] │
│                                                                             │
│   Progress: ════════════════░░░░░░░░░░░░░░░░░░░░░░░░░░░  Step 3/7           │
│                                                                             │
│   @customer              @order                @payment                     │
│       │                     │                     │                         │
│       │    :checkout        │                     │                         │
│       ╞════════════════════▶│                     │   ✓ Completed           │
│       │                     │                     │                         │
│       │                     ◆ cart not empty?     │   ✓ true → continue     │
│       │                     │                     │                         │
│       │                     │  :payment_request   │                         │
│       │                     ╞═════════════════ ▸ ▸│   ⟳ Animating...       │
│       │                     │                     │                         │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

Breakpoints ​

Pause at specific points:

on :checkout from @customer (api)
  ? cart is not empty                    ⏸ ← Breakpoint set
    order moves to #awaiting_payment
    emit :payment_request to @payment

Simulation paused at breakpoint:
  Guard: ? cart is not empty
  Result: true
  Context: { cart: { items: [...] }, total: 1225 }

  [Continue] [Step Into] [Skip Guard]

Context Inspector ​

View context state at any simulation step:

┌───────────────────────────────────────────────────────────┐
│ CONTEXT INSPECTOR                          Step 3 of 7   │
├───────────────────────────────────────────────────────────┤
│                                                           │
│ $order_id:    "ord-abc123"        (set at step 1)        │
│ $customer:    { id: "cust-456", email: "j@example.com" } │
│ $total:       1225                (unchanged)            │
│ $items:       ["Laptop", "Mouse"] (unchanged)            │
│                                                           │
│ STATE:        #awaiting_payment   (changed at step 2)    │
│                                                           │
│ PENDING:                                                  │
│   - Waiting for :payment_success from @payment           │
│   - Waiting for :payment_failed from @payment            │
│                                                           │
└───────────────────────────────────────────────────────────┘

Coverage Visualization ​

Coverage Heatmap ​

Overlay showing test coverage intensity:

┌─────────────────────────────────────────────────────────────────────────────┐
│ COVERAGE HEATMAP                                                            │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│   @customer              @order                @payment                     │
│       │                     │                     │                         │
│       │    :checkout        │                     │                         │
│       ├═══════════════════▶│                     │   ████ 7 tests          │
│       │                     │                     │                         │
│       │                     ◆ cart not empty?     │   ████ both branches    │
│       │                     │                     │                         │
│       │                     │  :payment_request   │                         │
│       │                     ├───────────────────▶│   ██░░ 2 tests          │
│       │                     │                     │                         │
│       │                     │  :payment_success   │                         │
│       │                     │◀────────────────────│   ██░░ 2 tests          │
│       │                     │                     │                         │
│       │                     │  :payment_failed    │                         │
│       │                     │◀--------------------│   ░░░░ 0 tests ⚠        │
│       │                     │                     │                         │
│                                                                             │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│   Legend: ████ High coverage   ██░░ Medium   ░░░░ None   ⚠ Untested        │
│                                                                             │
│   Overall: 85% events tested | 100% guards both branches | 90% states      │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

Coverage Summary Panel ​

┌───────────────────────────────────────────────────────────┐
│ COVERAGE SUMMARY                                          │
├───────────────────────────────────────────────────────────┤
│                                                           │
│ Events:                                                   │
│   :checkout              ████████████ 7 tests             │
│   :payment_success       ████░░░░░░░░ 2 tests             │
│   :payment_failed        ████░░░░░░░░ 2 tests             │
│   :ship                  ████░░░░░░░░ 2 tests             │
│   :cancel                ░░░░░░░░░░░░ 0 tests ⚠           │
│                                                           │
│ Guards:                                                   │
│   ? cart is not empty    ✓ both branches                  │
│   ? payment successful   ✓ both branches                  │
│   ? $total > 1000        ✓ both branches                  │
│   ? $retry_count < 3     ░ only true tested ⚠             │
│                                                           │
│ States:                                                   │
│   #awaiting_payment      ✓ entry/exit tested              │
│   #paid                  ✓ entry tested                   │
│   #shipped               ✓ entry tested                   │
│   #cancelled             ░ not tested ⚠                   │
│                                                           │
├───────────────────────────────────────────────────────────┤
│ Total Coverage: 87% (26/30 paths)                         │
└───────────────────────────────────────────────────────────┘

Untested Path Highlighting ​

@customer              @order                @payment
    │                     │                     │
    │    :checkout        │                     │
    ├────────────────────▶│                     │
    │                     │                     │
    │                     ◆ cart not empty?     │
    │                     │                     │
    │            ┌────────┴────────┐            │
    │            │                 │            │
    │         [true]            [false]         │
    │            │                 │            │
    │            │          ┌─────────────────┐ │
    │            │          │ UNTESTED PATH   │ │  ← Red highlight
    │            │          │ :empty_cart_err │ │
    │            │          └─────────────────┘ │
    │            │                              │

Technical Implementation ​

Rendering Architecture ​

┌─────────────────────────────────────────────────────────────────────────────┐
│                          NarrativeBoard Renderer                            │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│   .flow file                                                                │
│       │                                                                     │
│       ▼                                                                     │
│   ┌──────────────┐                                                          │
│   │    Parser    │ → AST (Abstract Syntax Tree)                             │
│   └──────┬───────┘                                                          │
│          │                                                                  │
│          ▼                                                                  │
│   ┌──────────────┐                                                          │
│   │   Analyzer   │ → Graph Model (actors, events, states, guards)           │
│   └──────┬───────┘                                                          │
│          │                                                                  │
│          ▼                                                                  │
│   ┌──────────────┐                                                          │
│   │   Layouter   │ → Positioned Graph (x, y coordinates)                    │
│   └──────┬───────┘                                                          │
│          │                                                                  │
│          ├─────────────────────┬─────────────────────┐                      │
│          ▼                     ▼                     ▼                      │
│   ┌──────────────┐      ┌──────────────┐      ┌──────────────┐              │
│   │  SVG Render  │      │  PNG Render  │      │ HTML Render  │              │
│   └──────────────┘      └──────────────┘      └──────┬───────┘              │
│          │                     │                     │                      │
│          │                     │                     ▼                      │
│          │                     │              ┌──────────────┐              │
│          │                     │              │  Interactive │              │
│          │                     │              │   Controls   │              │
│          │                     │              └──────────────┘              │
│          │                     │                     │                      │
│          ▼                     ▼                     ▼                      │
│        .svg                  .png                  .html                    │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

SVG Structure ​

xml
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
  <!-- Definitions -->
  <defs>
    <marker id="arrow" .../>
    <marker id="async-arrow" .../>
    <pattern id="diamond" .../>
  </defs>

  <!-- Actor Lanes -->
  <g class="actor-lanes">
    <g class="actor" data-actor="customer">
      <rect class="lane-header" .../>
      <text class="lane-title">@customer</text>
      <line class="lane-timeline" .../>
    </g>
    <!-- More actors... -->
  </g>

  <!-- Scenarios (Collapsible) -->
  <g class="scenario" data-scenario="checkout" data-collapsed="false">
    <rect class="scenario-header" .../>
    <text class="scenario-title">scenario: checkout</text>

    <!-- Given Section -->
    <g class="given-section">...</g>

    <!-- Event Flows -->
    <g class="event-flow">
      <path class="event-arrow" d="..." marker-end="url(#arrow)"/>
      <text class="event-label">:checkout</text>
    </g>

    <!-- Decision Diamond -->
    <g class="decision">
      <polygon class="diamond" points="..."/>
      <text class="guard-label">? cart not empty</text>
    </g>

    <!-- State Badge -->
    <g class="state-badge" data-state="awaiting_payment">
      <rect class="badge-bg" .../>
      <text class="badge-label">#awaiting_payment</text>
    </g>

    <!-- Expect Section -->
    <g class="expect-section">...</g>
  </g>
</svg>

Interactive HTML Template ​

html
<!DOCTYPE html>
<html>
<head>
  <title>NarrativeBoard: order.flow</title>
  <style>
    /* Collapsible regions */
    .scenario[data-collapsed="true"] .scenario-content { display: none; }
    .actor[data-hidden="true"] { opacity: 0.3; }

    /* Test markers */
    .assertion.pass { color: #40c057; }
    .assertion.fail { color: #fa5252; }

    /* Coverage heatmap */
    .coverage-high { fill: #40c057; }
    .coverage-medium { fill: #fab005; }
    .coverage-low { fill: #fa5252; }

    /* Simulation highlight */
    .current-step { stroke-width: 3; stroke: #228be6; }
  </style>
</head>
<body>
  <!-- Controls -->
  <div id="controls">
    <button onclick="expandAll()">Expand All</button>
    <button onclick="collapseAll()">Collapse All</button>
    <button onclick="toggleCoverage()">Coverage</button>
    <button onclick="startSimulation()">▶ Simulate</button>
  </div>

  <!-- Diagram -->
  <div id="diagram-container">
    <!-- SVG rendered here -->
  </div>

  <!-- Context Panel -->
  <aside id="context-panel">
    <h3>Context</h3>
    <pre id="context-json"></pre>
  </aside>

  <!-- Simulation Controls -->
  <div id="simulation-controls" style="display: none;">
    <button onclick="prevStep()">◀ Prev</button>
    <button onclick="nextStep()">▶ Next</button>
    <button onclick="autoPlay()">▶▶ Play</button>
    <input type="range" id="speed" min="1" max="10" value="5"/>
    <button onclick="resetSimulation()">↻ Reset</button>
  </div>

  <script src="narrativeboard.js"></script>
</body>
</html>

CLI Commands ​

Generate NarrativeBoard ​

bash
# Default NarrativeBoard (replaces --type=combined)
eventflow diagram order.flow

# Explicit NarrativeBoard type
eventflow diagram order.flow --type=narrative

# Specific scenario only
eventflow diagram order.flow --type=narrative --scenario="checkout"

# Multiple scenarios
eventflow diagram order.flow --type=narrative --scenario="checkout,payment failure"

# Interactive HTML output
eventflow diagram order.flow --type=narrative --format=html

# Serve locally with hot reload
eventflow diagram order.flow --type=narrative --serve

# Export formats
eventflow diagram order.flow --type=narrative --format=svg --output=order-diagram.svg
eventflow diagram order.flow --type=narrative --format=png --output=order-diagram.png
eventflow diagram order.flow --type=narrative --format=pdf --output=order-diagram.pdf

Coverage Mode ​

bash
# Generate with coverage overlay
eventflow diagram order.flow --type=narrative --coverage

# Coverage from specific test file
eventflow diagram order.flow --type=narrative --coverage --tests=order.test.flow

# Coverage threshold warning
eventflow diagram order.flow --type=narrative --coverage --min-coverage=80

Simulation Mode ​

bash
# Open in simulation mode
eventflow diagram order.flow --type=narrative --simulate

# Simulate specific scenario
eventflow diagram order.flow --type=narrative --simulate --scenario="checkout"

# Auto-play simulation
eventflow diagram order.flow --type=narrative --simulate --autoplay

# Record simulation as GIF
eventflow diagram order.flow --type=narrative --simulate --record=simulation.gif

Collapse Options ​

bash
# Start with all scenarios collapsed
eventflow diagram order.flow --type=narrative --collapsed

# Expand specific scenario
eventflow diagram order.flow --type=narrative --expand="checkout"

# Hide specific actors
eventflow diagram order.flow --type=narrative --hide-actors="@inventory,@shipping"

Examples ​

E-Commerce Checkout ​

Source: order.flow

flow
machine: @order

scenario: successful checkout

  given:
    @customer is logged in
    cart contains:
      | product | price |
      | Laptop  | 1200  |
      | Mouse   | 25    |
    $total: number is 1225

  on :checkout from @customer (api)
    ? cart is not empty
      order moves to #awaiting_payment
      emit :payment_request to @payment
        with $order_id, $total

    expect:
      = order is in #awaiting_payment
      = :payment_request was emitted to @payment

  on :payment_success from @payment
    order moves to #paid
    emit :reserve_stock to @inventory
      with $order_id, $items

  on :stock_reserved from @inventory
    order moves to #confirmed
    emit :confirmation to @customer

  expect:
    = order is in #confirmed
    = @customer received :confirmation

Generated NarrativeBoard:

╔═══════════════════════════════════════════════════════════════════════════════════════════╗
║                           @order · NarrativeBoard                                         ║
╠═══════════════════════════════════════════════════════════════════════════════════════════╣
║                                                                                           ║
║  ▼ scenario: successful checkout                                                    PASS  ║
║  │                                                                                        ║
║  │  given:                                                                                ║
║  │    ✓ @customer is logged in                                                            ║
║  │    ✓ cart contains: Laptop ($1200), Mouse ($25)                                        ║
║  │    ✓ $total is 1225                                                                    ║
║  │                                                                                        ║
║  │  ┌───────────────┐  ┌───────────────┐  ┌───────────────┐  ┌───────────────┐            ║
║  │  │  @customer    │  │    @order     │  │   @payment    │  │  @inventory   │            ║
║  │  └───────┬───────┘  └───────┬───────┘  └───────┬───────┘  └───────┬───────┘            ║
║  │          │                  │                  │                  │                    ║
║  │          │   :checkout      │                  │                  │                    ║
║  │          ├═════════════════▶│                  │                  │                    ║
║  │          │                  │                  │                  │                    ║
║  │          │                  ◆ cart not empty?  │                  │                    ║
║  │          │                  │ [true] ✓         │                  │                    ║
║  │          │                  │                  │                  │                    ║
║  │          │                  │[#awaiting_payment]                  │                    ║
║  │          │                  │                  │                  │                    ║
║  │          │                  │ :payment_request │                  │                    ║
║  │          │                  ├─────────────────▶│                  │                    ║
║  │          │                  │                  │                  │                    ║
║  │          │       expect: ✓ order is in #awaiting_payment                               ║
║  │          │                ✓ :payment_request was emitted to @payment                   ║
║  │          │                  │                  │                  │                    ║
║  │          │                  │                  │                  │                    ║
║  │          │                  │:payment_success  │                  │                    ║
║  │          │                  │◀─────────────────┤                  │                    ║
║  │          │                  │                  │                  │                    ║
║  │          │                  │    [#paid]       │                  │                    ║
║  │          │                  │                  │                  │                    ║
║  │          │                  │           :reserve_stock            │                    ║
║  │          │                  ├─────────────────────────────────────▶│                   ║
║  │          │                  │                  │                  │                    ║
║  │          │                  │                  │                  │                    ║
║  │          │                  │         :stock_reserved             │                    ║
║  │          │                  │◀─────────────────────────────────────┤                   ║
║  │          │                  │                  │                  │                    ║
║  │          │                  │ [#confirmed]     │                  │                    ║
║  │          │                  │                  │                  │                    ║
║  │          │   :confirmation  │                  │                  │                    ║
║  │          │◀═════════════════│                  │                  │                    ║
║  │          │                  │                  │                  │                    ║
║  │                                                                                        ║
║  │  expect:                                                                               ║
║  │    ✓ order is in #confirmed                                                            ║
║  │    ✓ @customer received :confirmation                                                  ║
║  │                                                                                        ║
║  └────────────────────────────────────────────────────────────────────────────────────────║
║                                                                                           ║
║  ▶ scenario: checkout with empty cart                                              PASS   ║
║  ▶ scenario: payment failure                                                       PASS   ║
║                                                                                           ║
╠═══════════════════════════════════════════════════════════════════════════════════════════╣
║  [◀ Prev] [▶ Next] [▶▶ Play] [Coverage: 94%] [Expand All] [Collapse All]                  ║
╚═══════════════════════════════════════════════════════════════════════════════════════════╝

SVG Rendering:

@order · NarrativeBoard▼scenario: successful checkoutPASSgiven:✓@customer is logged in✓cart contains: Laptop ($1200), Mouse ($25)✓$total is 1225@customer@order@payment@inventory:checkoutAPI?cart not empty?[true] ✓#awaiting_payment:payment_requestexpect:✓ order is in #awaiting_payment ✓ :payment_request emitted:payment_success#paid:reserve_stock:stock_reserved#confirmed:confirmationexpect:✓order is in #confirmed✓@customer received :confirmation▶scenario: checkout with empty cartPASS▶scenario: payment failurePASS◀ Prev▶ Next▶▶ PlayCoverage: 94%Expand AllCollapse All◆ = Guard█ = State→ = Event✓ = Pass

Migration from Current Diagrams ​

Compatibility ​

NarrativeBoard is designed as a replacement, not an addition:

CurrentNarrativeBoardNotes
--type=laneDefault viewActor lanes are always shown
--type=stateState badges inlineStates shown within the flow
--type=combinedFull NarrativeBoardEverything in one view

Deprecation Plan ​

  1. Phase 1: Introduce NarrativeBoard as --type=narrative
  2. Phase 2: Make NarrativeBoard the default (--type defaults to narrative)
  3. Phase 3: Deprecate --type=lane, --type=state, --type=combined with warnings
  4. Phase 4: Remove deprecated types (major version)

Configuration ​

yaml
# eventflow.yaml
diagram:
  default_type: narrative  # or lane/state/combined for backward compat

  narrative:
    default_collapsed: false
    show_coverage: true
    show_context_panel: true


Open Questions ​

  1. Performance: How to handle very large systems (50+ actors, 100+ events)?

    • Proposed: Virtual scrolling, progressive loading, focus mode
  2. Print Output: How should NarrativeBoard look when printed to PDF?

    • Proposed: Auto-expand all, hide controls, optimize for A3 landscape
  3. Dark Mode: Should NarrativeBoard support dark mode?

    • Proposed: Yes, with CSS variables for theming
  4. Accessibility: How to make NarrativeBoard accessible?

    • Proposed: ARIA labels, keyboard navigation, screen reader support
  5. Embedding: How to embed NarrativeBoard in external docs?

    • Proposed: <iframe> embed code, exported HTML, web components

Changelog ​

VersionDateChanges
v1.02025-12-16Initial proposal

Appendix: Visual Reference ​

Color Palette ​

ColorUsageHex
BlueEvents, arrows#228be6
GreenSuccess states, passing tests#40c057
RedFailure states, failing tests#fa5252
YellowWarning, pending#fab005
GrayNeutral, disabled#868e96
WhiteBackground#ffffff
DarkText#212529

Icon Reference ​

IconMeaning
▶Collapsed region
▼Expanded region
◆Decision/guard point
✓Passed assertion
✗Failed assertion
○Not executed
⏳Wait point
⏸Breakpoint/pause

Typography ​

ElementFontSize
Actor nameSystem UI, Bold12px
Event nameMonospace11px
State nameMonospace10px
Guard textSystem UI, Italic10px
AssertionSystem UI10px

Released under the MIT License.