← writing
spec · v1.6 · src · 4,414 LOC · tests · 367 green · modules · 7
Lens
← → switch · ↑ ↓ navigate inside · Esc close
Everything. Start here.
System map · cycle of one session

Anatomy of a runner that doesn't trust what it runs.

When the framework runs, it loops: pick a task, call Claude to work, check the result, repeat. Each turn is a session — and every session crosses ten stations. The runner directs traffic; the LLM does the work; canonical state stays out of its reach.

Why this matters and how the rubber-stamp problem motivated each defense — see Keeping the loop honest →

Vocabulary · read first
8 terms that recur across the dashboard
Runner supervisor
The Python orchestrator. Runs in a loop, decides what to execute, and never trusts what the LLM returns.
LLM worker
Claude, executed by the runner as a subprocess. Does the work but is treated as untrusted by default.
Session
One call to Claude. Single purpose: run one phase (plan, implement, or verify) of one task.
Task
A unit of work. Has a title, description, list of acceptance criteria, dependencies, and current state.
spec.json file
The canonical state. Lists every task with its phase, status, criteria, and history. Lives in the workspace.
PIV
Plan → Implement → Verify. The standard cycle of every task. Plan sketches, Implement codes, Verify audits.
AC
Acceptance Criteria. The list of conditions a task must satisfy to be marked done.
Defense layer
A mechanism the runner uses to protect itself from the LLM. Snapshot+revert, AC freeze, redaction, etc.

Through the rest of the dashboard, these four colors recur: violet for runner-owned, amber for LLM-owned, cyan for defenses, plum for files.

Defenses · 10 layers
Stations · cycle of one session
Files · 9 in workspace
D1 · LOCKFILE→ S1
One runner at a time
Locks the workspace via fcntl. A second runner aborts on the spot.
D2 · BACKUP / RESTORE→ S2
Spec self-healing
Backup before each session. If the spec corrupts, the runner heals it itself.
D3 · LIMITS & CASCADE→ S3
Auto-skip
Hard caps. Tasks that stall are skipped; dependents cascade-skip.
D4 · SNAPSHOT→ S4
State photo
Before the LLM call, the runner photographs critical fields in RAM.
D5 · PROCESS GROUP→ S5
Isolated subprocess
Separate process group. 30-min timeout, cascading kill if it stalls.
D6 · REDACTION→ S6
Erase secrets
16 alternation branches scrub API keys, tokens, and DB URLs before any disk write.
D7 · TAMPERING REVERT→ S7
Diff and undo
Compare snapshot vs disk. Anything outside the whitelist gets written back.
D8 · TWO-PASS GATE→ S8
Evidence + score
Auditor → Lead. Score recomputed by the runner; the LLM cannot declare its own grade.
D9 · AC FREEZE→ S8/S9
Hidden criteria
Frozen at plan→implement. The Lead always judges the frozen copy, never the live one.
D10 · STATE INTEGRITY→ S7
Hash + RAM authoritative
SHA-256 on the rubber-stamp state file. Diverged hash → restore from memory.
01
Lock the workspace
First thing the runner does: open a lockfile. Mutual exclusion guaranteed.
›
02
Validate the spec
Reads and verifies the task file. If corrupt, restores itself from backup.
›
03
Pick the next task
Selection algorithm. Skips stuck tasks, respects dependencies.
›
04
Snapshot the state
Pre-session: copies the runner-owned fields into RAM.
›
phase & LLM zone ↓
05
Call the LLM
Subprocess runs Claude. Anything it touches is suspect until proven otherwise.
›
untrusted From here through post-session, every write to spec.json is treated as suspect. The runner re-reads from disk to check.
06
Redact secrets, then write
Mandatory scrub before anything reaches disk.
›
07
Check for tampering
Re-reads the spec, diffs it against the snapshot, undoes anything off-contract.
›
if phase == verify ↓
08
Audit the delivery · two-pass
Runs only when the phase is verify. Two separate audits, three post-parse defenses.
›
Pass 1
Auditor
Read-only session. Audits the code under 8 lenses. Output bracketed by UUIDs.
→
Pass 2
Lead
Re-validates each finding, runs an independent sweep, checks AC, emits the verdict.
09
Advance the phase
Move forward. On FAIL, return to plan and increment the cycle counter.
›
10
Check if it's done
All tasks done? Exit. Otherwise, back to station 01.
›
↻ loop · next session begins at S1
workspace/.ralph.lock
Workspace lockfile. Holds the active runner's PID. Released on exit (including crash).
spec.json
Canonical state. Every task with its phase, status, AC, and history. Both runner and LLM write; runner reverts off-contract changes.
.spec.json.bak
Pre-session backup. Bit-for-bit copy. Used by D2 if validation fails.
.handoff.md
Ephemeral note from the runner to the next session. Re-read fresh every turn.
.plans/<id>.md
Plan output. One markdown file per task. The reference document for implement.
.verify_reports/<id>-cycle<N>.json
Lead verdict. One per verify cycle, per task. Schema-validated, hard caps.
.rubber_stamp_state.json
Detector state. Streak counter, recent P2 titles, last lead summary. Hash-protected.
.probes_baseline.txt
Test baseline. Output of the configured test command from the last passing cycle.
.history/{sessions,runs}/
Durable observability. Structured per-session and per-run logs. All redacted before write.