Story and epic fields
Status: Shipped Generated from app @ 1b3d5a69d73473db077dfb44f4390b42cded6bd4 Regenerate: pnpm gen:reference
A story or epic is a Markdown file with YAML frontmatter, or an HTML file with <meta name="cs:…"> tags. Both formats carry the same fields. Every field is optional.
What makes a file a story
A file is a story (a work item with a status) when its type is one of: story, bug, spike. Any other type, or none, keeps it a plain document: it still syncs and appears in the file tree, but it isn’t treated as a story.
Fields
| Markdown key | HTML meta name | Type | Legacy | What it's for |
|---|---|---|---|---|
status | cs:status | string | — | The item's status: one of the team's statuses (see status-taxonomy.yml). |
type | cs:type | string | — | Document type. story, bug and spike make the file a board item; any other value, or none, keeps it a plain document. |
depends_on | cs:depends-on | list of string | — | Story ids this story depends on. Drives the dependency graph. |
tags | cs:tags | list of string | — | Free-form tags, for example [infra, urgent]. |
supporting_docs | cs:supporting-docs | list of string | — | Relative paths to supporting documents. |
story_id | cs:story-id | string | — | The story's display id, for example W-5. |
source_repo | cs:source-repo | string | — | The repo the story's code lives in, as owner/repo. |
dev_branch | cs:dev-branch | string | yes | Legacy. Read only as a fallback on older documents; use branch. |
branch_name | cs:branch-name | string | yes | Legacy. Read only as a fallback on older documents; use branch. |
team | cs:team | string | — | The team the document belongs to. |
done.completed_at | cs:done.completed_at | string | — | When the story was completed. In Markdown it's nested: done: { completed_at: … }. |
repos | cs:repos | list of string | — | Epics: the repos the epic spans, as owner/repo. |
branch | cs:branch | string | — | Stories: the story's branch, used to create its worktree. Epics: the integration branch (default integration/<epic-id>). |
scope_context | cs:scope-context | list of string | — | Epics: top-level directories the epic's workspace round-trips as context. |
scope_install | cs:scope-install | list of string | — | Epics: top-level directories the epic's workspace inherits without writing back. |
sprint | cs:sprint | string | — | The sprint the story belongs to, for example 2026-08-A. |
points | cs:points | number | — | Estimate in points. A non-numeric value is ignored. |
assigned_to | cs:assigned-to | string | — | Who the story is assigned to (a username). |
rank | cs:rank | string | — | Order within a board column. The board writes it; you rarely set it by hand. |
points is read as a number. Values off the scale 1, 2, 3, 5, 8, 13 get a warning from validate_story, but they’re kept.
The same story in both formats
---
type: story
story_id: W-5
status: in-progress
depends_on: [W-3]
sprint: 2026-08-A
points: 3
source_repo: ledgerline/web
---
# Export to CSV <meta name="cs:type" content="story">
<meta name="cs:story-id" content="W-5">
<meta name="cs:status" content="in-progress">
<meta name="cs:depends-on" content="W-3">
<meta name="cs:sprint" content="2026-08-A">
<meta name="cs:points" content="3">
<meta name="cs:source-repo" content="ledgerline/web">
<title>Export to CSV</title> In HTML, list fields are comma-separated. Either attribute order works: <meta name="cs:status" content="todo"> or <meta content="todo" name="cs:status">. The title comes from <title>, or the first <h1>.
Your own fields
Any other key is kept as a custom field. An HTML meta name maps to its Markdown key by turning dashes into underscores: cs:risk-tier is the same field as risk_tier. Field names are case-insensitive.
Generated from app @ 1b3d5a69d73473db077dfb44f4390b42cded6bd4 Regenerate: pnpm gen:reference
How we know this is accurate 2 sources
Checked against the app at 1b3d5a69d73473db077dfb44f4390b42cded6bd4.
Code
-
src-tauri/src/commands/pipeline_format/mod.rs -
src-tauri/src/commands/pipeline_format/html.rs