> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/snarktank/ralph/llms.txt
> Use this file to discover all available pages before exploring further.

# Ralph Converter

> Convert PRDs to prd.json format for autonomous execution by the Ralph agent

The Ralph Converter skill (`/ralph`) converts markdown PRDs into the `prd.json` format that Ralph uses for autonomous execution. It ensures stories are properly sized, ordered by dependencies, and have verifiable acceptance criteria.

## Overview

The skill takes a PRD (markdown file or text) and converts it to `prd.json` in your project's ralph directory. The conversion process:

1. Validates story sizes (must fit in one context window)
2. Orders stories by dependencies (schema → backend → UI)
3. Ensures acceptance criteria are verifiable
4. Adds required criteria (typecheck, browser verification)
5. Archives previous runs if needed

## Usage

Invoke the skill with any of these trigger phrases:

```
Convert tasks/prd-user-auth.md to prd.json
Turn this PRD into ralph format
Create prd.json from this
Generate ralph json for the notification system PRD
```

Or explicitly load it:

```
Load the ralph skill and convert [path-to-prd] to prd.json
```

## Output Format

The skill generates a `prd.json` file with this structure:

<CodeGroup>
  ```json prd.json theme={null}
  {
    "project": "[Project Name]",
    "branchName": "ralph/[feature-name-kebab-case]",
    "description": "[Feature description from PRD title/intro]",
    "userStories": [
      {
        "id": "US-001",
        "title": "[Story title]",
        "description": "As a [user], I want [feature] so that [benefit]",
        "acceptanceCriteria": [
          "Criterion 1",
          "Criterion 2",
          "Typecheck passes"
        ],
        "priority": 1,
        "passes": false,
        "notes": ""
      }
    ]
  }
  ```
</CodeGroup>

### Field Descriptions

<ParamField body="project" type="string" required>
  Project name (derived from PRD or repository)
</ParamField>

<ParamField body="branchName" type="string" required>
  Git branch name in kebab-case, prefixed with `ralph/`
</ParamField>

<ParamField body="description" type="string" required>
  Brief feature description from PRD introduction
</ParamField>

<ParamField body="userStories" type="array" required>
  Array of user story objects ordered by dependency and priority
</ParamField>

<ParamField body="userStories[].id" type="string" required>
  Sequential ID: US-001, US-002, etc.
</ParamField>

<ParamField body="userStories[].title" type="string" required>
  Short descriptive title from PRD
</ParamField>

<ParamField body="userStories[].description" type="string" required>
  User story in standard format: "As a \[user], I want \[feature] so that \[benefit]"
</ParamField>

<ParamField body="userStories[].acceptanceCriteria" type="array" required>
  Verifiable criteria that define "done". Always includes "Typecheck passes" and "Verify in browser using dev-browser skill" for UI stories.
</ParamField>

<ParamField body="userStories[].priority" type="number" required>
  Execution order (1 = highest). Based on dependencies, then document order.
</ParamField>

<ParamField body="userStories[].passes" type="boolean" required>
  Whether story is complete. Always starts as `false`.
</ParamField>

<ParamField body="userStories[].notes" type="string" required>
  Learnings from implementation. Always starts empty.
</ParamField>

## The Number One Rule: Story Size

**Each story must be completable in ONE Ralph iteration (one context window).**

Ralph spawns a fresh AI instance per iteration with no memory of previous work. If a story is too big, the LLM runs out of context before finishing and produces broken code.

### Right-sized Stories ✅

* Add a database column and migration
* Add a UI component to an existing page
* Update a server action with new logic
* Add a filter dropdown to a list

### Too Large ❌ (Split These)

* "Build the entire dashboard" → Split into: schema, queries, UI components, filters
* "Add authentication" → Split into: schema, middleware, login UI, session handling
* "Refactor the API" → Split into one story per endpoint or pattern

<Note>
  **Rule of thumb:** If you cannot describe the change in 2-3 sentences, it's too big.
</Note>

## Story Ordering: Dependencies First

Stories execute in priority order. Earlier stories must not depend on later ones.

### Correct Order ✅

<Steps>
  <Step title="Schema/Database Changes">
    Database migrations, table creation, column additions
  </Step>

  <Step title="Server Actions / Backend Logic">
    API endpoints, server functions, business logic
  </Step>

  <Step title="UI Components">
    Frontend components that use the backend
  </Step>

  <Step title="Dashboard/Summary Views">
    Higher-level views that aggregate data
  </Step>
</Steps>

### Wrong Order ❌

```
1. US-001: UI component (depends on schema that doesn't exist yet)
2. US-002: Schema change (should have been first)
```

## Acceptance Criteria: Must Be Verifiable

Each criterion must be something Ralph can CHECK, not something vague.

### Good Criteria ✅

* "Add `status` column to tasks table with default 'pending'"
* "Filter dropdown has options: All, Active, Completed"
* "Clicking delete shows confirmation dialog"
* "Typecheck passes"
* "Tests pass"

### Bad Criteria ❌

* "Works correctly" (too vague)
* "User can do X easily" (not measurable)
* "Good UX" (subjective)
* "Handles edge cases" (which ones?)

### Required Criteria

The skill automatically adds to every story:

```
"Typecheck passes"
```

For stories with UI changes, it also adds:

```
"Verify in browser using dev-browser skill"
```

<Note>
  Frontend stories are NOT complete until visually verified. Ralph will use the dev-browser skill to navigate to the page, interact with the UI, and confirm changes work.
</Note>

## Conversion Rules

The skill follows these rules when converting:

1. **Each user story becomes one JSON entry** - One-to-one mapping
2. **IDs are sequential** - US-001, US-002, etc.
3. **Priority based on dependencies** - Then document order
4. **All stories start incomplete** - `passes: false`, empty `notes`
5. **branchName derived from feature** - Kebab-case, prefixed with `ralph/`
6. **Typecheck always added** - Every story includes "Typecheck passes"

## Splitting Large PRDs

If a PRD has big features, the skill splits them into smaller stories:

### Original Story

```markdown theme={null}
### US-001: Add user notification system
**Description:** As a user, I want to receive notifications about important events.

**Acceptance Criteria:**
- [ ] Notifications stored in database
- [ ] Notification bell icon in header
- [ ] Dropdown panel shows notifications
- [ ] Can mark notifications as read
- [ ] Preferences page to control notifications
```

### Split Into Smaller Stories

```json theme={null}
[
  {
    "id": "US-001",
    "title": "Add notifications table to database",
    "description": "As a developer, I need to store notifications in the database.",
    "acceptanceCriteria": [
      "Create notifications table with id, user_id, message, read, created_at",
      "Generate and run migration",
      "Typecheck passes"
    ],
    "priority": 1
  },
  {
    "id": "US-002",
    "title": "Create notification service",
    "description": "As a developer, I need a service to create and query notifications.",
    "acceptanceCriteria": [
      "createNotification() function saves to database",
      "getUnreadNotifications() returns unread for user",
      "markAsRead() updates read status",
      "Typecheck passes"
    ],
    "priority": 2
  },
  {
    "id": "US-003",
    "title": "Add notification bell icon to header",
    "description": "As a user, I want to see when I have notifications.",
    "acceptanceCriteria": [
      "Bell icon shows in header for authenticated users",
      "Badge shows unread count if > 0",
      "Clicking bell toggles dropdown panel",
      "Typecheck passes",
      "Verify in browser using dev-browser skill"
    ],
    "priority": 3
  },
  {
    "id": "US-004",
    "title": "Create notification dropdown panel",
    "description": "As a user, I want to see my notifications in a dropdown.",
    "acceptanceCriteria": [
      "Dropdown shows list of notifications (most recent first)",
      "Unread notifications visually distinct",
      "Empty state when no notifications",
      "Clicking notification marks as read",
      "Typecheck passes",
      "Verify in browser using dev-browser skill"
    ],
    "priority": 4
  },
  {
    "id": "US-005",
    "title": "Add notification preferences page",
    "description": "As a user, I want to control which notifications I receive.",
    "acceptanceCriteria": [
      "Preferences page accessible from dropdown",
      "Checkboxes for each notification type",
      "Saves preferences to database",
      "Typecheck passes",
      "Verify in browser using dev-browser skill"
    ],
    "priority": 5
  }
]
```

Each story is now one focused change that can be completed and verified independently.

## Example Conversion

Here's a complete example of converting a PRD:

### Input PRD

<CodeGroup>
  ```markdown tasks/prd-task-status.md theme={null}
  # Task Status Feature

  Add ability to mark tasks with different statuses.

  ## Requirements
  - Toggle between pending/in-progress/done on task list
  - Filter list by status
  - Show status badge on each task
  - Persist status in database
  ```
</CodeGroup>

### Output JSON

<CodeGroup>
  ```json prd.json theme={null}
  {
    "project": "TaskApp",
    "branchName": "ralph/task-status",
    "description": "Task Status Feature - Track task progress with status indicators",
    "userStories": [
      {
        "id": "US-001",
        "title": "Add status field to tasks table",
        "description": "As a developer, I need to store task status in the database.",
        "acceptanceCriteria": [
          "Add status column: 'pending' | 'in_progress' | 'done' (default 'pending')",
          "Generate and run migration successfully",
          "Typecheck passes"
        ],
        "priority": 1,
        "passes": false,
        "notes": ""
      },
      {
        "id": "US-002",
        "title": "Display status badge on task cards",
        "description": "As a user, I want to see task status at a glance.",
        "acceptanceCriteria": [
          "Each task card shows colored status badge",
          "Badge colors: gray=pending, blue=in_progress, green=done",
          "Typecheck passes",
          "Verify in browser using dev-browser skill"
        ],
        "priority": 2,
        "passes": false,
        "notes": ""
      },
      {
        "id": "US-003",
        "title": "Add status toggle to task list rows",
        "description": "As a user, I want to change task status directly from the list.",
        "acceptanceCriteria": [
          "Each row has status dropdown or toggle",
          "Changing status saves immediately",
          "UI updates without page refresh",
          "Typecheck passes",
          "Verify in browser using dev-browser skill"
        ],
        "priority": 3,
        "passes": false,
        "notes": ""
      },
      {
        "id": "US-004",
        "title": "Filter tasks by status",
        "description": "As a user, I want to filter the list to see only certain statuses.",
        "acceptanceCriteria": [
          "Filter dropdown: All | Pending | In Progress | Done",
          "Filter persists in URL params",
          "Typecheck passes",
          "Verify in browser using dev-browser skill"
        ],
        "priority": 4,
        "passes": false,
        "notes": ""
      }
    ]
  }
  ```
</CodeGroup>

## Archiving Previous Runs

Before writing a new `prd.json`, the skill checks if there's an existing one from a different feature:

1. **Read current `prd.json`** (if it exists)
2. **Check if `branchName` differs** from the new feature's branch name
3. **If different AND `progress.txt` has content:**
   * Create archive folder: `archive/YYYY-MM-DD-feature-name/`
   * Copy current `prd.json` and `progress.txt` to archive
   * Reset `progress.txt` with fresh header

<Note>
  The `ralph.sh` script handles archiving automatically when you run it, but if you're manually updating prd.json between runs, the skill will archive for you.
</Note>

## Workflow

<Steps>
  <Step title="Have a PRD Ready">
    Create a PRD using the [PRD Generator](/skills/prd-generator) skill or write one manually in `tasks/prd-[feature-name].md`
  </Step>

  <Step title="Convert to JSON">
    Invoke the Ralph converter:

    ```
    Load the ralph skill and convert tasks/prd-feature-name.md to prd.json
    ```
  </Step>

  <Step title="Review and Edit">
    Review the generated `prd.json`. Check:

    * Story sizes are appropriate
    * Dependencies are in correct order
    * Acceptance criteria are verifiable
  </Step>

  <Step title="Run Ralph">
    Start the autonomous execution loop:

    ```bash theme={null}
    ./scripts/ralph/ralph.sh
    ```
  </Step>
</Steps>

## Validation Checklist

Before saving `prd.json`, the skill verifies:

* [ ] **Previous run archived** (if prd.json exists with different branchName)
* [ ] Each story is completable in one iteration (small enough)
* [ ] Stories are ordered by dependency (schema → backend → UI)
* [ ] Every story has "Typecheck passes" as criterion
* [ ] UI stories have "Verify in browser using dev-browser skill" as criterion
* [ ] Acceptance criteria are verifiable (not vague)
* [ ] No story depends on a later story

## Next Steps

After generating `prd.json`:

1. **Review** - Check story sizes and ordering
2. **Commit** - Add the prd.json to version control
3. **Run Ralph** - Execute `./scripts/ralph/ralph.sh` to start autonomous implementation
4. **Monitor** - Check `progress.txt` for learnings and `git log` for commits

## Common Issues

### Stories Too Large

If Ralph consistently fails to complete stories:

* Each story should be 2-3 sentences maximum
* Split into smaller, more focused stories
* Check for multiple logical changes in one story

### Wrong Dependency Order

If stories fail due to missing dependencies:

* Ensure schema changes come before backend logic
* Backend logic must exist before UI can use it
* Move dependent stories to later in the priority order

### Vague Acceptance Criteria

If Ralph can't determine when a story is complete:

* Replace "works correctly" with specific behaviors
* Add concrete UI states or API responses
* Include specific file paths or function names
