Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

livt - Living Text

Collaborate on board. Make it living in text.

Outcome

Collaborative outcomes evolve alongside the product as living text.

Opportunities

  • Stale Discovery: Discovery-phase artifacts are not persisted after synchronous collaboration sessions
  • Discovery-Development Gap: Persisted discovery artifacts are not leveraged in the development process

Solutions

  • Provide a CLI tool that captures collaborative outcomes as text files (YAML, Markdown)
  • Track consistency across artifacts via ID-based references with automated checks
  • Treat Formulation artifacts (Gherkin scenarios) as generated output, not the source of truth — the master lives in Discovery artifacts

Live Demo

livt dogfoods itself: its own discovery artifacts — stories, story maps, example mappings, and ubiquitous language — are published with livt build as a live demo. It shows exactly what the guides below describe.

Installation

livt ships as a single static binary. Every release is built by the release workflow on GitHub Actions, and every artifact is:

  • listed in checksums.txt (SHA-256)
  • signed with a GitHub artifact attestation (Sigstore build provenance) tying it to the exact source commit and workflow run
  • built from the module as served by the Go module proxy and verified against the Go checksum database, so the binaries can be reproduced from the public source

Pick the method that matches how much of that verification you want automated.

The mise github backend downloads the release binary and verifies its build provenance attestation by default — a tampered or foreign-built asset fails to install.

mise use "github:boykush/livt@<version>"

Or in mise.toml:

[settings]
lockfile = true # pin checksum + provenance in mise.lock

[tools]
"github:boykush/livt" = "<version>"

With lockfile = true, the asset checksum and attestation provenance are recorded in mise.lock, so later installs — on CI or a teammate’s machine — must match bit-for-bit.

Manual download

Download the archive for your platform and checksums.txt from GitHub Releases, then verify before running:

# Provenance: proves the artifact was built by this repository's release
# workflow on GitHub Actions (requires the GitHub CLI)
gh attestation verify livt_<version>_<os>_<arch>.tar.gz --repo boykush/livt

# Integrity: check the SHA-256 checksum (macOS: shasum -a 256 -c)
sha256sum --check --ignore-missing checksums.txt

tar -xzf livt_<version>_<os>_<arch>.tar.gz
install livt ~/.local/bin/ # or anywhere on your PATH

Build from source

Source installs are verified by the Go checksum database: everyone gets byte-identical source for a given version, and a silently re-pushed tag is rejected. Pin a release version rather than latest so installs stay reproducible.

go install github.com/boykush/livt@<version>

Or with the mise go backend (requires Go on your PATH):

mise use "go:github.com/boykush/livt@<version>"

Getting Started

Installation

Install with mise, which verifies the release binary’s build provenance attestation by default:

mise use "github:boykush/livt@<version>"

See Installation for all methods and how release artifacts are verified.

Quick Start

  1. Create the required directories:
mkdir -p stories discoveries/usm discoveries/example-mappings ubiquitous
  1. Create your first story in stories/my-first-story.md:
---
name: My first story
---

As a user
I want to do something
So that I get value
  1. Build and serve:
livt serve
  1. Open http://localhost:3000 in your browser. Every page has a sidebar to switch between Example Mappings, Story Maps, Stories, and Ubiquitous Language. Open Stories to find the story you just created:

Stories list and sidebar navigation

Stories

Stories are Markdown files with YAML frontmatter, stored in the stories/ directory. The stories/ directory is the committed story registry: once a story candidate is committed for detailed discovery, its key is owned by stories/{story-key}.md.

Format

---
name: Story display name
---

Story body in Markdown.

The name field in frontmatter is required. The story key is derived from the filename (without .md). Story keys must be kebab-case, using lowercase letters, numbers, and hyphens. Key uniqueness is enforced by the filesystem: two committed stories cannot use the same stories/{story-key}.md path.

Example

stories/confirm-story-map.md:

---
name: Confirm story map
---

As a team member
I want to view the story map as a board
So that I can visually confirm the discovery outcomes maintained in text

This story has key confirm-story-map, which is used to reference it from story maps and example mappings.

Commit from a story map

Committing a story candidate from a story map into the registry is handled by the /story-commit skill (from the discovery-facilitator plugin), rather than a CLI command. Given the story map and the candidate, it creates stories/{story-key}.md first and then writes the same key back to the matching candidate in the story map.

Story detail page

Story Maps

Story maps are YAML files stored in discoveries/usm/. They define the structure of a User Story Map with activities, steps, stories, and release slices.

Format

name: Map Name

activities:
  - key: activity-key
    name: Activity Name
    steps:
      - key: step-key
        name: Step Name
        stories:
          - key: story-key
            name: Story Card Name
            release: release-id
          - name: Lightweight Story Card

releases:
  - id: release-id
    name: Release Name

ubiquitous:
  - term-key

Ubiquitous Language

  • ubiquitous is optional: each entry is a ubiquitous language term key
  • Referenced terms render as pink stickies below the board, linking to ubiquitous.html#{term-key}
  • A key with no matching term file renders as a plain pink card

Releases

  • Each release defines a horizontal divider on the board
  • Each release has an id that story cards reference with release
  • Stories with a release appear above that release’s divider
  • A release without name defaults to “Release N” based on position
  • Stories not in any release appear below all dividers
  • Story cards without key appear as plain cards and can still belong to a release
  • A story can reference only one release

Example

discoveries/usm/collaborative-discovery.yaml:

name: Collaborative Discovery

activities:
  - key: story-mapping
    name: Story Mapping
    steps:
      - key: discover-stories
        name: Discover stories
        stories:
          - key: confirm-story-context
            name: Confirm story context
            release: walking-skeleton
          - key: confirm-story-map
            name: Confirm story map
            release: walking-skeleton
          - name: Draft session outcomes
      - key: slice-releases
        name: Slice into releases
        stories:
          - key: split-release-scope
            name: Split release scope
            release: release-2

  - key: discovery
    name: Discovery
    steps:
      - key: discover-rules
        name: Discover rules
        stories:
          - key: confirm-discovery-outcomes
            name: Confirm discovery outcomes
            release: walking-skeleton

releases:
  - id: walking-skeleton
    name: Walking Skeleton
  - id: release-2

Story map board

Example Mappings

Example mappings are YAML files stored in discoveries/example-mappings/. They capture the rules, examples, and questions discovered during an Example Mapping session for a story.

Format

story: story-key

rules:
  - id: R-01
    name: Rule description
    examples:
      - id: EX-01
        name: Example description
    issues:
      - https://github.com/owner/repo/issues/1
    automated: true

questions:
  - id: Q-01
    text: Question text

ubiquitous:
  - term-key
  • story is optional (links to the corresponding story detail page)
  • IDs must be unique within their rule or question list
  • ubiquitous is optional: each entry is a ubiquitous language term key, rendered as a pink sticky linking to ubiquitous.html#{term-key}. A key with no matching term file renders as a plain pink card.
  • issues is optional: the rule’s automation Issue URLs on implementation repos (Issue URLs only). The master records the links; their state lives at the URL target. A rule without issues is unlinked.
  • automated is optional: records the judgment that the rule is actually automated by tests, which is independent of Issues being filed or closed. Absent means not automated. Set it when the rule’s automation lands; unset it when the rule changes.

Visual Layout

The board renders cards in the Example Mapping format:

  • Yellow card: Story (top)
  • Blue cards: Rules (row below story)
  • Green cards: Examples (stacked under their rule)
  • Red cards: Questions (separate column)
  • Pink cards: Ubiquitous language terms (referenced via ubiquitous, below the board)

Example

discoveries/example-mappings/confirm-discovery-outcomes.yaml:

rules:
  - id: R-01
    name: An example mapping can be rendered as a sticky view with only a story reference
    examples:
      - id: EX-01
        name: A YAML with only a story reference displays a single yellow Story card

  - id: R-02
    name: Cards are laid out following the Example Mapping format
    examples:
      - id: EX-01
        name: Rules are displayed as blue cards in a row below the Story card
      - id: EX-02
        name: Examples are displayed as green cards stacked under their Rule
      - id: EX-03
        name: Questions are displayed as red cards in a separate column

questions: []

Example mapping board

Ubiquitous Language

Ubiquitous language terms are Markdown files with YAML frontmatter, stored in the ubiquitous/ directory. Each file is a single term, and livt renders them as a table you can browse like a database.

Format

---
name: Term display name
---

Definition in Markdown.

The name field in frontmatter is the display term. The term key is derived from the filename (without .md) and must be kebab-case, using lowercase letters, numbers, and hyphens. The body is the term’s definition.

Example

ubiquitous/story-map.md:

---
name: Story Map
---

A board to overview activities, steps, and stories alongside release slices.

Visual Layout

livt build renders every term as a row on a single page at ubiquitous.html, with Term, Key, and Definition columns. Each row carries an id={term-key} anchor, so a term is linkable as ubiquitous.html#{term-key}.

Referencing terms from boards

Story maps and example mappings can declare the terms they use with a top-level ubiquitous list of term keys:

ubiquitous:
  - story-map
  - story

Referenced terms render as pink stickies below the board, each linking to its glossary row (ubiquitous.html#{term-key}). A key with no matching ubiquitous/{term-key}.md file renders as a plain pink card, so references degrade gracefully. See Story Maps and Example Mappings.

Commands

livt serve

Build artifacts and start a local server.

While the server is running, livt watches the input directories (discoveries/example-mappings, stories, discoveries/usm, and ubiquitous). When a file changes, livt rebuilds and reloads the page in the browser automatically, so you can preview refinements while editing.

livt serve [flags]
FlagShortDefaultDescription
--port-p3000Port to listen on
--out-odistOutput directory

livt build

Build static HTML from artifacts without starting a server.

livt build [flags]
FlagShortDefaultDescription
--out-odistOutput directory

livt mcp

Run an MCP (Model Context Protocol) server that exposes the discovery master (story maps, stories, example mappings, and the ubiquitous language). An implementation repo’s coding agent can then fetch the spec for a story or rule without reading livt’s source.

The master usually lives in a separate checkout from the consumer, so point at it with --root or the LIVT_ROOT environment variable. The flag takes precedence; both default to the current directory.

livt mcp [flags]
FlagDefaultDescription
--root$LIVT_ROOT, then .Path to the livt project root holding the discovery master
--http(off; stdio)Serve over Streamable HTTP at this address (e.g. localhost:5488) instead of stdio; the MCP endpoint is <addr>/mcp

Transports

By default the server runs over stdio, spawned per consumer — the client launches livt mcp as a subprocess. This suits a single repo with the master checked out alongside it.

Pass --http to instead serve over Streamable HTTP from one long-running process, so several repos on the same machine can share a single server without each holding a checkout of the master:

livt mcp --http localhost:5488

Each consumer points its MCP client at http://localhost:5488/mcp. The server is stateless and read-only, so one process backs many clients; keep git pull current on its checkout and the served spec (and spec_version) updates live. For distributing this client configuration to implementation repos, see the livt-mcp plugin. This mode assumes local use with no authentication — the server is meant to bind to localhost, not a public network.

Tools

ToolArgumentsReturns
list_storiesEvery story with its key and name. Each entry links to its story resource (uri); stories that have an example mapping also include example_mapping_uri.
list_story_mapsEvery story map with its name and its story map resource URI (uri).

Resources

The spec itself is exposed as resources, addressable by URI (story map → story → mapping → rule, with ubiquitous terms linked from mappings and story maps):

URIReturns
livt://story-map/{map_name}A story map: activities, steps, story cards, and releases. Committed story cards link to their story resource. {map_name} is the map’s display name (percent-encoded) — the same identifier the build output uses for story-map/{name}.html.
livt://story/{story_key}The story’s name, body, and frontmatter meta (e.g. issue), plus example_mapping_uri when a mapping exists.
livt://mapping/{story_key}The story’s example mapping (rules, examples, questions, ubiquitous terms). Each rule carries its own uri, and ubiquitous_terms resolves each referenced term to its resource URI.
livt://mapping/{story_key}/rule/{rule_id}A single rule and its examples, plus its recorded automation: issues (automation Issue URLs) and automated (whether the rule is automated by tests). Rules inside livt://mapping/{story_key} carry the same fields.
livt://ubiquitous/{term_key}A ubiquitous language term’s name and definition.

Read them with resources/read; all appear in resources/templates/list. The server advertises templates only — there is no concrete resource list and no change notification (subscribe); every read is served fresh from disk.

Every tool and resource payload also includes a spec_version field – the short git revision of the master – so consumers can tell which version of the spec they are reading and detect drift.

livt version

Print the version of livt.

livt version

File Structure

Input

project-root/
  stories/
    {story-key}.md                        # Story files
  discoveries/
    usm/
      {map-name}.yaml                     # Story map files
    example-mappings/
      {story-key}.yaml                    # Example mapping files
  ubiquitous/
    {term-key}.md                         # Ubiquitous language term files
  • Story keys are derived from filenames (without extension)
  • Story keys must be kebab-case: lowercase letters, numbers, and hyphens
  • The stories/ directory is the committed story registry, and stories/{story-key}.md provides story key uniqueness
  • Example mapping filenames must match story keys to link them
  • Term keys are derived from ubiquitous/{term-key}.md filenames and used as ubiquitous.html#{term-key} link anchors

Output

livt build generates the following structure:

dist/
  index.html                              # Example mappings overview (home)
  story-maps.html                         # Story maps overview
  stories.html                            # Story list
  ubiquitous.html                         # Ubiquitous language table
  story/
    {story-key}.html                      # Story detail pages
  mapping/
    {story-key}.html                      # Example mapping boards
  story-map/
    {map-name}.html                       # Story map boards

Every page shares a left sidebar that links the four resource types (Example Mappings, Story Maps, Stories, Ubiquitous Language). The overview pages render each example mapping and story map as a preview card.