Skip to content
OpenPlanr Docs
LearnGitHub (opens in a new tab)

Spec-driven planning files (schema 1.0.0)

This is the file-level reference for spec-driven mode: what the planr-spec, planr-plan, and planr-ship skills write under .planr/specs/, and what the openplanr spec commands validate. The canonical JSON Schemas live in packages/protocol/schemas/v1.0.0; the CLI and the planr-pipeline package read the same contract with no conversion layer.

When authoring these files by hand, use the templates below verbatim.

Schema version: 1.0.0 Pinning rule: the schemaVersion field on every artifact MUST match the reader's expected version. Breaking changes start in the Protocol schema source and are mirrored here before release.


Directory layout

Every spec is a self-contained directory under .planr/specs/:

plaintext
.planr/specs/SPEC-NNN-{slug}/
├── SPEC-NNN-{slug}.md            # the functional spec (one per directory)
├── design/                       # optional — UI mockups + design-spec
│   ├── *.png                     # PNG mockups attached via `openplanr spec attach-design`
│   └── design-spec.md            # written by the designer agent
├── stories/
│   └── US-NNN-{slug}.md          # user stories scoped to this spec
├── tasks/
│   └── T-NNN-{slug}.md           # tasks scoped to this spec
├── qa-report.md                  # written by the QA agent after planr-ship
├── error-report.md               # written if a task fails 3 iterations
└── .pipeline-shipped             # written by planr-ship — proof of execution

ID scoping rule: in spec-driven mode, US-NNN and T-NNN are scoped to their parent SPEC, not project-globally unique. Two specs can each have their own US-001. Disambiguate via path or via the specId frontmatter field.


SPEC frontmatter

yaml
---
id: "SPEC-001"                    # required · format: SPEC-\d{3}
title: "User authentication"      # required · human-readable title
slug: "auth"                      # required · URL-safe lowercase, used in path
schemaVersion: "1.0.0"            # required · pinned to reader version
status: "pending"                 # required · pending | shaping | shaped | decomposing | decomposed | in-pipeline | done
priority: "P0"                    # required · P0 | P1 | P2 | P3
milestone: "v1.0"                 # optional · links to a milestone or release
po: "product-owner"               # optional · spec owner (Product Owner)
created: "2026-04-26"             # required · ISO date (YYYY-MM-DD)
updated: "2026-04-26"             # required · ISO date, bumped on edit
ui_files: []                      # required · array of PNG paths under design/ (empty if none)
tech_dependencies: []             # required · array of strings; informational only
---

Field meanings

FieldTypeMeaning
idstringProject-globally unique. Format SPEC-NNN (3-digit). The directory MUST be SPEC-NNN-{slug}/.
titlestringDisplay title. Human-readable.
slugstringURL-safe lowercase. Used in the directory name and in story and task slugs.
schemaVersionstringPinned schema version. 1.0.0 currently. Readers MUST refuse mismatched versions.
statusenumLifecycle marker: pending (just created) → shaping (questions in progress) → shaped (body authored) → decomposing (planning in progress) → decomposed (stories and tasks written) → in-pipeline (ship in progress) → done (shipped).
priorityenumP0 (must) / P1 (should) / P2 (nice) / P3 (defer).
milestonestring?Optional release/milestone tag.
postring?Optional Product Owner identifier (email or username).
created / updatedstringISO 8601 date. Bumped automatically by openplanr spec commands.
ui_filesarrayList of PNG file paths under design/. Non-empty lists route the designer agent.
tech_dependenciesarrayFree-form list of upstream tech dependencies. Informational; not consumed automatically.

SPEC body sections (in order)

The spec body uses the following H2 sections. openplanr spec shape writes them from interactive questions; the planr-plan skill reads them.

  1. ## Context & Goal — 2-5 sentences on the user need + outcome
  2. ## Functional Requirements — bullet list, action verbs
  3. ## Business Rules — constraints and validations
  4. ## User Flows — numbered step-by-step flows
  5. ## Out of Scope — explicit non-goals
  6. ## Acceptance Criteria — Given/When/Then bullets
  7. ## Notes for Decomposition (optional) — hints for planning, NOT requirements

The ## Notes for Decomposition section is freeform prose hinting at the intended story split, special attention areas, or files to preserve. The planr-plan skill reads it to bias its output. Example:

markdown
- Suggested US split: auth flow (UI), session management (Tech)
- Special attention: the delete flow needs a confirmation dialog
- Preserve: do not modify the existing UserService

Story frontmatter

Stories live at .planr/specs/SPEC-NNN-{slug}/stories/US-NNN-{story-slug}.md.

yaml
---
id: "US-001"                      # required · format: US-\d{3} (scoped to parent SPEC)
title: "Login form"               # required
specId: "SPEC-001"                # required · MUST match parent spec id
slug: "login-form"                # required · URL-safe; matches filename suffix
schemaVersion: "1.0.0"            # required
status: "pending"                 # required · pending | in-progress | done
priority: "P0"                    # required · P0 | P1 | P2 | P3
created: "2026-04-26"             # required
updated: "2026-04-26"             # required
---

Story body sections

markdown
# US-001 — Login form

> **Spec:** SPEC-001

## Story
As a **<role>** I want **<action>** so that **<benefit>**.

## Scope
<2-3 sentences describing what's in scope for this story>

## Acceptance Criteria

- [ ] Given <context>, when <action>, then <observable outcome>.
- [ ] Given …, when …, then …

## Dependencies
<Optional: tasks or stories this depends on, by id>

Task frontmatter

Tasks live at .planr/specs/SPEC-NNN-{slug}/tasks/T-NNN-{task-slug}.md.

yaml
---
id: "T-001"                       # required · format: T-\d{3} (scoped to parent SPEC)
title: "Build login form component" # required
storyId: "US-001"                 # required · MUST match a story id under the same spec
specId: "SPEC-001"                # required · MUST match the parent spec id
slug: "login-form-component"      # required · URL-safe; matches filename suffix
schemaVersion: "1.0.0"            # required
type: "UI"                        # required · "UI" | "Tech"
agent: "frontend-agent"           # required · subagent that owns this task
status: "pending"                 # required · pending | in-progress | done
created: "2026-04-26"             # required
updated: "2026-04-26"             # required
---

Type → agent mapping

typeDefault agentNotes
UIfrontend-agentUI-focused work: components, pages, styles
Techbackend-agentBackend, services, controllers, DTOs, migrations

The frontend-agent reads tasks where type: UI; the backend-agent reads tasks where type: Tech. Setting agent to a different value (e.g. a custom subagent name) overrides the default routing.

Task body sections

markdown
# T-001 — Build login form component

> **User Story:** US-001
> **Spec:** SPEC-001
> **Type:** UI
> **Agent:** `frontend-agent`

## Objective
<1-2 sentences: what does this task accomplish?>

## Files

### Create
- `src/components/auth/LoginForm.tsx`
- `src/components/auth/LoginForm.test.tsx`

### Modify
- `src/app/login/page.tsx` (mount the component)

### Preserve
- `src/app/layout.tsx` (do not touch)
- `package.json` (do not add dependencies)

## Technical Spec
<Implementation detail: libraries, patterns, integration points.
The frontend or backend agent reads this verbatim.>

## Test Requirements
<Build / test commands and DoD checks. The qa-agent reads this to
verify completion.>

## Definition of Done
- [ ] Code compiles (`npm run build`)
- [ ] Tests pass (`npm test`)
- [ ] Lint clean
- [ ] All Create files exist
- [ ] All Modify files updated only as described
- [ ] All Preserve files unchanged (verified via `git diff`)

The ### Create / ### Modify / ### Preserve lists are NOT optional — the qa-agent verifies them via git diff before accepting the task as done. A task that touches files outside these lists fails QA.


.pipeline-shipped marker

Written by the planr-ship skill at the end of a successful (or partially successful) run. This is the canonical proof that the work was shipped through the workflow, not a hand-authored Markdown file.

yaml
shipped_at: "2026-04-26T22:30:00Z"
pipeline_version: "0.4.0"
mode: "spec-driven"
feature: "auth"
tasks_executed: 3
tasks_failed: 0
qa_gate_status: "passed"
duration_seconds: 287
agents_invoked:
  - frontend-agent
  - backend-agent
  - qa-agent
  - devops-agent
  - doc-gen-agent
devops_status: "generated"
docs_status: "generated"
snapshot_status: "refreshed"
error_reports: []

If the marker is absent, the work was not shipped through the workflow. Audit trails reference this file by path: .planr/specs/SPEC-NNN-{slug}/.pipeline-shipped.


Status lifecycle (the full path)

A spec moves through these states, in order:

plaintext
pending → shaping → shaped → decomposing → decomposed → in-pipeline → done
StateSet byMeaning
pendingopenplanr spec createSpec directory exists; body is the empty template
shapingopenplanr spec shape (in progress)Q&A flow active
shapedopenplanr spec shape (complete)Spec body has Context/FRs/Rules/AC sections filled
decomposingplanr-plan skill (in progress)Stories and tasks are being written
decomposedplanr-plan skill (complete)stories/ and tasks/ are populated
in-pipelineplanr-ship skill (in progress)Implementation running
doneplanr-ship skill (complete)Tasks executed, QA passed, marker written

Schema version compatibility

The CLI, the skills, and the planr-pipeline package produce and consume schema 1.0.0. Breaking changes bump schemaVersion in lockstep. Keep them aligned:

bash
npm install -g openplanr@latest
openplanr setup
openplanr upgrade status

See also

OpenPlanr Docs
Commands for
Theme