The planning model
Status: ShippedCodeSense keeps your plan in plain files, not in a database. Each epic is a folder and each story is a file. The left nav, dependencies, sprints and your queries all read those files, and when you change a status in the app, CodeSense writes it back into the file.
The files live in your team’s context repo, under the team’s content/ folder. They travel through git like everything else there, and agents can read and write them directly.
Epics are folders
Every folder under content/ shows up as a group in the tree. A folder becomes an epic when it has a main doc. CodeSense looks for these names, in this order and ignoring case: README.md, index.md, README.html, index.html, README.htm, index.htm.
Epics nest to any depth, so a folder inside an epic is a sub-epic. Here’s the Ledgerline sample team:
- billing/content/planning /
- checkout-v2 / epic
- README.md epic main doc
- ll-231-cart-summary-tax-breakdown.md story
- ll-214-refund-endpoint-idempotency-keys.md story
- payments / sub-epic
- README.md sub-epic main doc
- ll-209-payment-intent-service.md story
- ll-222-wallet-pay-button.html HTML story
- invoicing-exports / epic
- README.md
- checkout-v2 / epic
The planning/ folder is just how the sample is laid out. CodeSense doesn’t require it. It skips folders whose names start with _ or ..
An epic’s main doc can carry its own frontmatter. The field CodeSense acts on is repos:, the list of source repos the epic spans (see Multi-repo):
---type: epictitle: Checkout v2status: in-progressrepos: [ledgerline/web, ledgerline/api]---Stories are files with a type
A file is a story when its metadata says type: story, type: bug or type: spike. The match ignores case. Anything else is treated as a plain document: no type:, or any other value such as epic or retro. A document still shows in the file tree, but it never gets a status, readiness or a place in a sprint.
---type: storystory_id: LL-231title: Cart summary tax breakdownstatus: reviewsource_repo: ledgerline/webdepends_on: [LL-204]sprint: sprint-14points: 3assigned_to: sam---
# LL-231 — Cart summary tax breakdown
## StoryAs a buyer I want to see subtotal, tax per jurisdiction, and total before I pay.The fields that drive the app:
| Field | What it does |
|---|---|
type | story, bug or spike. Required, or the file is a doc. |
story_id | The id other stories use in depends_on. It must be unique across your workspace. |
status | Where the story stands. Values come from your team’s statuses (see Statuses and phases). |
source_repo | The one repo this story’s agent works in, as owner/repo. |
depends_on | A YAML list of story_ids this story waits on. |
sprint, points, assigned_to | Planning metadata (see Stories and sprints). |
Any other key, such as area, risk or tags, is kept as metadata. You can filter and group on it in queries and dashboards. The full list is in Story and epic fields.
CodeSense reads the first ## Purpose or ## Story section as the story’s summary. Without one, the summary is blank.
Markdown or HTML, per file
A story or an epic main doc can also be an HTML page. In HTML, the same fields are <meta name="cs:…"> tags in the page head, with dashes in place of underscores: cs:story-id, cs:source-repo, cs:depends-on, cs:assigned-to. List values are comma-separated. The title comes from <title>, or from the first <h1> if there’s no title.
When you change the story’s status in the app, CodeSense rewrites the matching meta tag in place. Plan in HTML walks through one.
One index across the workspace
CodeSense keeps an index of every story’s metadata across all your teams. That is what lets depends_on use bare ids: a story can move to another folder and its links still resolve. If two stories share a story_id, neither one resolves until you fix the duplicate.
Checking a story
Agents can check their own work. The CodeSense MCP tools get_story_format and validate_story return the story contract and a list of findings, such as MISSING_SOURCE_REPO, UNPARSEABLE_FRONTMATTER, DUPLICATE_STORY_ID or MISSING_SUMMARY_HEADING. There’s no lint panel for people yet, so the quickest check is to ask your agent to validate the file. See Write your first story.
You can also create a story from New story in the app, a form with a template and a repo picker.
How we know this is accurate 11 sources
Checked against the app at 1b3d5a69d73473db077dfb44f4390b42cded6bd4.
Feature inventory
-
C-1 -
C-2 -
C-4 -
C-12 -
B-1
Code
-
src-tauri/src/commands/pipeline_format/mod.rs -
src-tauri/src/commands/pipeline_format/html.rs -
src-tauri/src/commands/pipeline_scanner.rs -
src-tauri/src/install/frontmatter_cache.rs -
src-tauri/src/mcp/story_authoring.rs -
src/shared/lib/pipeline-graph/find-enclosing-epic.ts