prd-schema
Scannednpx machina-cli add skill GantisStorm/essentials-claude-code/prd-schema --openclawprd.json schema reference from Ralph TUI. Use this when creating, editing, or reviewing .claude/prd/*.json files.
When to Use
Invoke /prd-schema before editing any prd.json file. Invoke /prd-schema validate <path> to check an existing file.
Conversion from Plans
prd.json files are typically created by /tasks-converter from architectural plans (.claude/plans/*-plan.md). The pipeline:
/plan-creator (or /bug-plan-creator, /code-quality-plan-creator)
↓ writes
.claude/plans/{slug}-{hash5}-plan.md
↓ consumed by
/tasks-converter <plan-path>
↓ writes
.claude/prd/<slug>.json
↓ executed by
/tasks-loop or /tasks-swarm or ralph-tui
How plan sections map to prd.json fields:
| Plan Section | prd.json Field |
|---|---|
## Summary | name, description |
## Files | One user story per file (typically) |
### Requirements | acceptanceCriteria[] |
### Reference Implementation | description (full code copied verbatim) |
### Migration Pattern | description (before/after code copied verbatim) |
## Dependency Graph | dependsOn[] (file deps translated to story IDs) |
## Exit Criteria | acceptanceCriteria[] |
| Plan path | metadata.planReference |
Each story's description must be 100% self-contained — the executor agent receives only the story description, never the source plan. All code, requirements, and verification commands are copied verbatim from the plan into the story.
Schema
Root Object
{
"name": "string (REQUIRED)",
"description": "string (optional)",
"branchName": "string (optional)",
"userStories": ["array (REQUIRED, see below)"],
"metadata": {
"createdAt": "ISO 8601 string (optional)",
"updatedAt": "ISO 8601 string (auto-set on write)",
"version": "string (optional)",
"sourcePrd": "string — path to source PRD markdown (optional)"
}
}
project is accepted as an alias for name, but name is preferred.
User Story Object
{
"id": "string (REQUIRED) — e.g. 'US-001'",
"title": "string (REQUIRED)",
"description": "string (optional)",
"acceptanceCriteria": ["string[] (optional)"],
"priority": "number (optional, default: 2) — 1=highest, 4=lowest",
"passes": "boolean (REQUIRED) — false=incomplete, true=complete",
"labels": ["string[] (optional)"],
"dependsOn": ["string[] (optional) — IDs of blocking stories"],
"notes": "string (optional)",
"completionNotes": "string (optional, alias for notes)"
}
Required Fields (validation fails without these)
| Scope | Field | Type |
|---|---|---|
| Root | name | string |
| Root | userStories | array (1+ elements) |
| Story | id | string |
| Story | title | string |
| Story | passes | boolean |
Unsupported Fields (rejected by Ralph TUI)
| Field | Why It's Wrong |
|---|---|
prd | Don't wrap content in a prd key |
tasks | Use userStories, not tasks |
status | Use passes (boolean), not status (string) |
subtasks | Flat list only, no nesting |
estimated_hours | No time tracking |
files | Not part of schema |
assignee | Not part of schema |
type | Not part of schema |
epic | Not part of schema |
parent | Not part of schema |
Dependencies
dependsOn is an array of story IDs. A story is blocked until all its dependencies have passes: true.
{
"id": "US-003",
"title": "Integration tests",
"dependsOn": ["US-001", "US-002"],
"passes": false
}
- If a dependency ID doesn't exist in the file, the story is treated as ready.
- Circular dependencies are not checked — ensure a valid DAG.
Task Selection Order
Ralph TUI selects the next task by:
- Filter to
passes: false - Filter to stories with all
dependsOnresolved (passes: true) - Sort by
priority(lowest number first) - Return first match
Minimal Valid Example
{
"name": "My Feature",
"userStories": [
{
"id": "US-001",
"title": "First task",
"passes": false
}
]
}
Complete Example
{
"name": "User Authentication",
"description": "Add user authentication to the application",
"branchName": "feature/auth",
"userStories": [
{
"id": "US-001",
"title": "Create login page",
"description": "Build login form with email and password fields.",
"acceptanceCriteria": [
"Form has email and password inputs",
"Form validates required fields",
"Submit button is disabled during submission"
],
"priority": 1,
"passes": false,
"dependsOn": []
},
{
"id": "US-002",
"title": "Implement authentication API",
"description": "POST /api/auth/login endpoint that verifies credentials and returns JWT.",
"acceptanceCriteria": [
"POST /api/auth/login accepts email and password",
"Returns JWT token on success",
"Returns 401 on invalid credentials"
],
"priority": 1,
"passes": false,
"dependsOn": []
},
{
"id": "US-003",
"title": "Connect login form to API",
"description": "Wire up the login form to call the authentication API.",
"acceptanceCriteria": [
"Form submits to /api/auth/login",
"Success stores token and redirects",
"Error shows message to user"
],
"priority": 2,
"passes": false,
"dependsOn": ["US-001", "US-002"]
}
],
"metadata": {
"createdAt": "2024-01-15T10:00:00Z",
"version": "1.0"
}
}
Instructions
Parse $ARGUMENTS to determine mode.
If $ARGUMENTS starts with validate:
Extract the path from $ARGUMENTS (e.g., /prd-schema validate .claude/prd/auth.json).
Read the file and check for schema violations:
# Check for rejected top-level fields
jq 'keys[] | select(. == "prd" or . == "tasks")' <path>
# Check every story has required fields
jq '.userStories[] | select(.id == null or .title == null or .passes == null) | .id // "unnamed"' <path>
# Check for unsupported story fields
jq '.userStories[] | to_entries[] | select(.key | test("^(subtasks|estimated_hours|files|status|assignee|type|epic|parent)$")) | "\(.key) in story"' <path>
Report each violation with the fix from the schema above.
If $ARGUMENTS is empty:
Output the schema summary:
prd.json Schema (Ralph TUI)
Root: name (req), description, branchName, userStories (req), metadata
Story: id (req), title (req), passes (req), description, acceptanceCriteria, priority, labels, dependsOn, notes, completionNotes
Rejected fields: prd, tasks, status, subtasks, estimated_hours, files, assignee, type, epic, parent
Use "passes: false" (not "status: open"). Use "userStories" (not "tasks").
Source
git clone https://github.com/GantisStorm/essentials-claude-code/blob/main/essentials/skills/prd-schema/SKILL.mdView on GitHub Overview
prd.json schema reference from Ralph TUI helps teams create, edit, and review PRD files. It validates the PRD structure and blocks unsupported fields to keep .claude/prd/*.json data consistent with the schema. This guardrail is essential for reliable plan-to-PRD conversion and downstream task execution.
How This Skill Works
It defines a Root Object schema (name, description, userStories, metadata) and a User Story object (id, title, description, acceptanceCriteria, priority, passes, labels, dependsOn, notes, completionNotes). Ralph TUI enforces required fields (name, userStories, id, title, passes), blocks unsupported fields (prd, tasks, status, subtasks, estimated_hours, files, assignee, type, epic, parent), and maps plan sections to prd.json fields during plan-to-PRD conversion (e.g., Summary → name/description). The root name supports an alias 'project' but 'name' is preferred.
When to Use It
- Before editing any prd.json file, run /prd-schema to verify structure.
- Run /prd-schema validate <path> to check an existing PRD for errors.
- When converting architectural plans to PRD, validate the generated .claude/prd/*.json before review.
- Check dependencies with dependsOn and ensure passes booleans reflect completion.
- Use the schema to keep PRD data consistent across plan-to-PRD workflows.
Quick Start
- Step 1: Run /prd-schema to validate your prd.json file.
- Step 2: Ensure required fields exist (name, userStories) and each story has id, title, passes.
- Step 3: Remove unsupported fields and re-validate until the schema passes.
Best Practices
- Require root name (or alias 'project') and a non-empty userStories array.
- Ensure every story has id, title, and a boolean passes field.
- Only use allowed fields; avoid the listed unsupported fields (prd, tasks, status, subtasks, estimated_hours, files, assignee, type, epic, parent).
- Keep plan-to-PRD mappings consistent with the mapping rules (Plan Section → prd.json Field).
- Validate dependsOn entries and maintain a correct DAG with all dependencies marked passes: true.
Example Use Cases
- Minimal PRD: {id:'US-001', title:'User authentication', passes:true, userStories:[{id:'US-001-1', title:'Login', passes:true}]}
- PRD with dependencies: {id:'US-002', title:'Password reset', dependsOn:['US-001'], passes:false}
- Plan-derived PRD: .claude/plans/auth-plan.md -> .claude/prd/auth.json with name 'User authentication'
- Rejected PRD due to an unsupported field: contains 'tasks' at root
- Alias usage: root name provided as 'project' alias instead of 'name' (name preferred)