ralph — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited ralph (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Converts existing PRDs to the prd.json format that Ralph uses for autonomous execution.
Convert tasks/<short-desc>/prd.md to tasks/<short-desc>/prd.json in the same folder.
Required arguments:
tasks/install-prereq-detection/). The folder name is <short-desc>.--issue <N> — GitHub issue number this PRD addresses. Required. The branch name embeds this.--prefix <type> — branch prefix per .claude/rules/git.md. One of feat | bug | task | audit | skill | agent. Default: feat.branchName in the produced JSON follows .claude/rules/git.md:
<prefix>/<issue#>-<short-desc>Example: folder tasks/install-prereq-detection/ + --issue 175 + --prefix task → branchName: "task/175-install-prereq-detection".
If --issue is missing, hard-fail with: "issue number required — open the GitHub issue first per .claude/rules/git.md and re-run with --issue <N>." This matches the project's "issue first, then branch" workflow.
The folder name IS the feature name — do not re-derive it from branchName or anywhere else.
{
"schemaVersion": 1,
"project": "[Project Name]",
"branchName": "<prefix>/<issue#>-<short-desc>",
"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": ""
}
]
}Each story must be completable in ONE Ralph iteration (one context window).
Ralph spawns a fresh Amp 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.
Rule of thumb: If you cannot describe the change in 2-3 sentences, it is too big.
Stories execute in priority order. Earlier stories must not depend on later ones.
Correct order:
Wrong order:
Each criterion must be something Ralph can CHECK, not something vague.
status column to tasks table with default 'pending'""Typecheck passes"For stories with testable logic, also include:
"Tests pass""Verify in browser using agent-browser skill"Frontend stories are NOT complete until visually verified. Ralph will use the agent-browser skill to navigate to the page, interact with the UI, and confirm changes work.
passes: false and empty notesralph/If a PRD has big features, split them:
Original:
"Add user notification system"
Split into:
Each is one focused change that can be completed and verified independently.
Input PRD:
# 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 databaseOutput prd.json:
{
"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 agent-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 agent-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 agent-browser skill"
],
"priority": 4,
"passes": false,
"notes": ""
}
]
}Archive fires only when all of the following hold for tasks/<short-desc>/:
prd.json already exists (re-running ralph on a feature that ran before).progress.txt has content beyond the header (the runner has written entries — there is execution history worth preserving).If both hold:
prd.json and progress.txt.tasks/<short-desc>/archive/<ISO-timestamp>/ where the timestamp is YYYY-MM-DDTHH-MM-SS (UTC; second-resolution avoids same-day collisions).prd.json and progress.txt into that directory.progress.txt to its header only: # progress
prd.json with the new conversion.Different branchNames do not trigger archiving. In the per-folder layout, a different feature lives in a different folder, so there is no shared slot to protect.
Before writing prd.json, verify:
tasks/<short-desc>/ — folder name is the feature nameprd.json exists AND progress.txt has run history, archived to tasks/<short-desc>/archive/<ISO-timestamp>/ before overwriting~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.