Skip to content

README format

Audience. Daily user.

At a glance

Every item lives at projects/YYYY-MM/YYYY-MM-DD-slug/README.md. The file opens with a header (item metadata) followed by an H1 title and the body content.

From condash v2.16.0 onward, the canonical header shape is YAML frontmatter — a ----delimited block at the top of the file. The legacy bold-prose shape (**Key**: value lines under the H1) is also accepted indefinitely, so you do not have to migrate existing READMEs unless you want to.

Field YAML key Bold-prose key Required Applies to Notes
Date date **Date** no all ISO YYYY-MM-DD. Defaults to the directory's date prefix when missing.
Kind kind **Kind** no all project / incident / document. Defaults to project.
Status status **Status** yes all now / review / later / backlog / done. Unknown values are preserved verbatim (no silent rewrite), log a parser warning, and surface a !? <value> badge on the card.
Apps apps (sequence) **Apps** no all YAML list of app names; legacy form is comma-separated, backtick-wrapped. Powers the per-app filter.
Branch branch **Branch** no projects Git branch name. Hints the /pr skill + worktree isolation rules.
Base base **Base** no projects Base branch for /pr. Defaults to origin/HEAD.
Environment environment **Environment** no incidents PROD / STAGING / DEV.
Severity severity **Severity** no incidents low / medium / high.
Severity impact severity_impact (combined into **Severity**) no incidents One-line user-visible impact.
Languages languages **Languages** no documents Output language for deliverables. en / fr / …

YAML keys are snake_case. Bold-prose keys are case-insensitive; values trimmed. Order does not matter in either shape. Unknown fields are silently ignored — safe to add your own.

Header shape — YAML frontmatter (canonical)

---
date: 2026-04-18
kind: project
status: now
apps:
  - helio
branch: feat/bench-harness
base: main
---

# Helio benchmark harness

## Goal

condash projects create emits this shape from v2.16.0 onward. To migrate existing bold-prose READMEs in the tree, run:

condash projects rewrite-headers --dry-run   # preview
condash projects rewrite-headers              # write

The verb is idempotent (already-YAML files are no-ops) and skips any README whose body has unexpected content between the meta block and the first ## heading — re-run after hand-editing those files.

Header shape — bold-prose (legacy, still accepted)

# Helio benchmark harness

**Date**: 2026-04-18
**Kind**: project
**Status**: now
**Apps**: `helio`
**Branch**: `feat/bench-harness`

## Goal

The parser scans every line between the title and the first ## heading. A line is treated as metadata if it matches **<Key>**: <value>. The first blank line is not a terminator — only the first ## heading is.

Both shapes feed the same parser output (src/main/parse.ts and src/shared/header.ts):

  • title — the H1 (frontmatter form: H1 below the closing ---; bold-prose form: H1 at the top).
  • date, kind, status (aka priority), apps, branch, base, extra (severity, environment, …) — typed fields.
  • summary — first paragraph after the first ## heading, truncated to 300 chars.
  • sections — every ## <heading> with checkboxes under it (see conception convention).
  • deliverables — every ## Deliverables link to a .pdf (see conception convention).

Examples

Project (YAML)

---
date: 2026-04-10
kind: project
status: now
apps:
  - notes.vcoeur.com
  - vcoeur.com
branch: feat/session-cookie-auth
base: main
---

# Migrate auth to session-cookie hybrid

## Goal

One-paragraph intent. Becomes the card summary.

## Scope
## Steps
- [ ] Audit current session-cookie usage
- [~] Implement hybrid read path
- [x] Decide cookie attributes

## Timeline
- 2026-04-10 — Project created

Incident (YAML)

---
date: 2026-04-14
kind: incident
status: review
apps:
  - vcoeur.com
environment: PROD
severity: high
severity_impact: Login returns 500 under concurrent load
---

# Login returns 500 under concurrent load

## Description

First paragraph is the card summary. Keep it one sentence for the dashboard.

## Timeline
- 2026-04-14 11:04 — Pager fires
- 2026-04-14 11:42 — Rollback to previous release
- 2026-04-14 14:20 — Root cause: connection pool exhaustion

environment and severity are incident-only in convention, but the parser will accept them on any kind. Nothing enforces the type split — the dashboard simply renders whatever it finds.

Document (YAML)

---
date: 2026-04-01
kind: document
status: review
apps:
  - notes.vcoeur.com
  - vcoeur.com
  - alicepeintures.com
languages:
  - fr
  - en
---

# GDPR audit — 2026 spring review

## Deliverables

- [Rapport technique](rapport-technique.pdf) — full French version with code references
- [Executive summary](summary-en.pdf) — one-page English abridgement

Status

Five values, in this exact order:

now → review → later → backlog → done

Anything outside this set is preserved verbatim — the parser does not rewrite the value. Two side-effects keep typos from slipping past:

  • The parser logs a WARNING with the offending value and the item's path, e.g. unknown Status 'wip' in projects/2026-04/2026-04-17-foo/README.md.
  • The card renders a red !? <value> badge next to the status pill, with a tooltip showing the valid enum. Sort order falls back to "after every known value" (per statusOrder in src/shared/projects.ts), so the typo sits visibly at the end of the list until corrected. The badge disappears as soon as the README is fixed — the next poll cycle re-parses, finds a valid Status, and drops the badge.

Backlog card showing a red !? WIP badge next to its status pill Backlog card showing a red !? WIP badge next to its status pill

Without the badge, a typo like active would silently sit at the tail of the sort with no visible marker; with it, the item sticks out until corrected.

See conception convention for the status model and what each value means.

Apps

YAML form: a sequence of plain strings (no backticks, no parentheticals).

apps:
  - vcoeur.com
  - notes.vcoeur.com
  - condash

Bold-prose form: comma-separated, backtick-wrapped. Trailing (…) parentheticals are stripped, so `vcoeur.com` (frontend) becomes vcoeur.com.

**Apps**: `vcoeur.com`, `notes.vcoeur.com`, `condash`

Either way, the resulting list powers the dashboard's per-app filter chips.

Step markers

The ## Steps list uses five canonical markers, recognised by the parser and round-tripped by every writer (CLI mutation verbs, GUI step-toggle, the markdown editor):

  • - [ ]todo. Not yet started.
  • - [~]doing. In flight.
  • - [x]done. Resolved successfully.
  • - [!]blocked. Surfacing a problem that needs attention; counts toward the milestone total but not toward resolved.
  • - [-]dropped. Resolved by removing the work; counts as resolved for the progress bar.

The canonical list lives in src/shared/types/project.ts (STEP_MARKERS). Any marker outside this set is treated as plain prose by the parser.

Body conventions

Header fields only describe the item's metadata. The body (everything after the title, in YAML form; everything after the first ##, in bold-prose form) carries the content — goal, scope, steps, timeline, deliverables, notes. See:

What the parser never looks at

  • TOML frontmatter — only ----delimited YAML is recognised.
  • ## sections other than Steps and Deliverables — rendered verbatim as Markdown; not parsed for structure.
  • notes/ subdirectories — indexed as files under the card but never mined for metadata.
  • Any file in the item directory other than README.md.