How Ralph's Priority Algorithm Selects the Next User Story

Ralph selects the next user story by filtering prd.json for unfinished stories where passes is false, sorting them by the numeric priority field in ascending order (lower numbers indicate higher priority), and returning the first item in that sorted list.

Ralph, an open-source autonomous development agent from the snarktank/ralph repository, uses a deterministic priority-based selection method to decide which feature to implement next. Understanding Ralph's priority algorithm for story selection is essential for teams structuring their Product Requirements Documents (PRDs) to ensure critical functionality gets built first.

How the Priority Algorithm Works

The algorithm follows a straightforward four-step process encoded in Ralph's core instructions:

  1. Load the PRD: Ralph reads prd.json (or the JSON generated by the PRD skill) containing the userStories array.
  2. Filter incomplete work: It filters the array to retain only entries where "passes": false.
  3. Sort by priority: It sorts the remaining stories by their priority value in ascending numerical order, where a lower integer represents higher business priority.
  4. Select the winner: It returns the first story from the sorted results—the highest-priority unfinished item.

Handling Ties

When two stories share identical priority values, Ralph preserves JSON order and selects whichever appears first in the filtered list. This deterministic tie-breaker ensures consistent, repeatable behavior across iterations.

Source Code Implementation

The selection logic is explicitly defined in Ralph's instruction files rather than buried in complex code:

  • In prompt.md, the directive states: "Pick the highest priority user story where passes: false" (lines 10-11).
  • In README.md, the workflow step reads: "Pick the highest priority story where passes: false" (lines 124-125).

These files demonstrate that Ralph treats story selection as a data-driven decision based strictly on the PRD's metadata fields, making the prd.json structure the single source of truth for work sequencing.

Practical Code Examples

You can replicate Ralph's selection logic locally to preview which story the agent will tackle next.

JavaScript Implementation

import { readFileSync } from 'fs';

// Load the PRD
const prd = JSON.parse(readFileSync('prd.json', 'utf-8'));

// Filter unfinished stories, sort by priority ascending, pick first
const nextStory = prd.userStories
  .filter(story => story.passes === false)
  .sort((a, b) => a.priority - b.priority)[0];

if (nextStory) {
  console.log(`Next: ${nextStory.title} (Priority: ${nextStory.priority})`);
} else {
  console.log('All stories have passed—Ralph is done!');
}

Bash and jq One-Liner

jq -r '
  .userStories
  | map(select(.passes == false))
  | sort_by(.priority)
  | .[0]
  | "ID: \(.id)\nTitle: \(.title)\nPriority: \(.priority)"
' prd.json

Both snippets mirror the exact filter-then-sort-by-priority-ascending logic implemented in the snarktank/ralph source files.

Summary

  • Ralph reads prd.json to access the userStories array defined in prd.json.example.
  • Unfinished stories (where passes: false) are candidates for selection.
  • The algorithm sorts by ascending priority values, meaning priority 1 outranks priority 5.
  • The first item after sorting becomes the active development target.
  • Ties defer to JSON document order for deterministic selection.

Frequently Asked Questions

Does Ralph support weighted priorities or MoSCoW classification?

No. According to the snarktank/ralph source code, Ralph expects simple numeric priorities where lower integers indicate higher urgency. The algorithm performs a basic ascending sort on the priority field without supporting textual classifications like "Must have" or "Should have."

What happens if all user stories have passes: true?

If every story in prd.json has "passes": true, the filter step returns an empty array. Ralph will have no candidate stories to sort or select, effectively signaling that the project is complete or awaiting new requirements in the PRD.

Can I use negative numbers or decimals for priority values?

The algorithm performs a numeric sort, so negative numbers and decimals are technically valid. However, Ralph's documentation in README.md suggests using positive integers starting from 1 for clarity, as this matches the standard convention referenced in the priority algorithm description.

Where is the selection logic actually executed?

While the algorithm is documented in prompt.md and README.md, the actual execution depends on the Amp AI tool processing these instructions. The logic is prompt-based rather than hardcoded in a specific function file, making the PRD structure itself the controlling authority for Ralph's workflow.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →