
Ralph
- 29 installs
- 40 repo stars
- Updated August 4, 2026
- akillness/skills-template
Ralph (Ouroboros) is an agent skill for specification-first AI development that interviews vague ideas into immutable specs, then executes and loops autonomously until verification passes.
About
Ralph (Ouroboros) is a skill for specification-first AI development. A developer uses it to crystallize vague requirements into an immutable spec via Socratic interviewing before writing code, then execute and loop autonomously until verification passes. It provides ooo commands, Nine Minds lateral-thinking agents, drift detection, and a persistent Ralph loop with state files across Claude Code, Codex CLI, Gemini CLI, and OpenCode.
- Socratic interviewing crystallizes an immutable spec at Ambiguity <= 0.2
- Persistent Ralph loop with state files runs until verification passes
- Nine Minds personas break stagnation across four agent platforms
Ralph by the numbers
- 29 all-time installs (skills.sh)
- Ranked #9,417 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
ralph capabilities & compatibility
- Capabilities
- spec first development · socratic interview · autonomous loop · drift detection · orchestration
- Use cases
- planning · orchestration · code review
What ralph says it does
Socratic interviewing crystallizes vague ideas into immutable specs (Ambiguity ≤ 0.2) before any code is written.
Ralph mode loops with state persistence until verification passes — the boulder never stops.
Stop prompting. Start specifying.
npx skills add https://github.com/akillness/skills-template --skill ralphAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 29 |
|---|---|
| repo stars | ★ 40 |
| Last updated | August 4, 2026 |
| Repository | akillness/skills-template ↗ |
What it does
Run Socratic interviewing to reach an immutable spec (Ambiguity <= 0.2), then execute a Double Diamond run and loop autonomously with state persistence until verification passes.
Who is it for?
Turning vague requirements into an immutable spec and looping autonomous agents until a task is verified complete.
Skip if: Quick one-off edits where full spec-first interviewing and looping is overkill.
When should I use this skill?
You say ralph, ooo, stop prompting, start specifying, or need guaranteed completion before writing code.
What you get
A verified deliverable produced from an immutable spec with drift measured against it.
- Immutable YAML seed spec
- Executed and verified implementation
- Ralph loop state files and progress reports
By the numbers
- Nine Minds agents
- Ambiguity <= 0.2 gate
- Convergence at Similarity >= 0.95
Files
ralph (Ouroboros) — Specification-First AI Development
Stop prompting. Start specifying.
>
"The beginning is the end, and the end is the beginning."
The serpent doesn't repeat — it evolves.
>
Most AI coding fails at the input, not the output. Ouroboros fixes the human, not the machine.
---
When to use this skill
- Before writing any code — expose hidden assumptions with Socratic interviewing (Ambiguity ≤ 0.2 required)
- Vague requirements — crystallize into an immutable YAML seed spec before touching the keyboard
- Long-running tasks needing autonomous iteration until verified completion
- Guaranteed completion tasks — Ralph loop persists across session boundaries until verification passes
- When stuck — Nine Minds lateral thinking personas break through stagnation
- Drift detection — measure deviation from original seed and course-correct before it's too late
- Ontology convergence — evolutionary loop runs until consecutive generations are ≥ 0.95 similar
---
Core Architecture: The Ouroboros Loop
Interview → Seed → Execute → Evaluate
↑ ↓
└──── Evolutionary Loop ────┘Each cycle evolves, not repeats. Evaluation output feeds back as input for the next generation until the system converges.
Double Diamond
◇ Wonder ◇ Design
╱ (diverge) ╱ (diverge)
╱ explore ╱ create
╱ ╱
◆ ──────────── ◆ ──────────── ◆
╲ ╲
╲ define ╲ deliver
╲ (converge) ╲ (converge)
◇ Ontology ◇ EvaluationFirst diamond (Socratic): diverge into questions → converge into ontological clarity. Second diamond (Pragmatic): diverge into design options → converge into verified delivery.
You cannot design what you haven't understood. The first diamond is a prerequisite for the second.
---
Commands
| Command | Triggers | What It Does |
|---|---|---|
ooo interview | ooo interview, interview me, clarify requirements, socratic questioning | Socratic questioning until Ambiguity ≤ 0.2 |
ooo seed | ooo seed, crystallize, generate seed, freeze requirements | Crystallize into immutable YAML spec |
ooo run | ooo run, execute seed, ouroboros run | Execute via Double Diamond |
ooo evaluate | ooo evaluate, 3-stage check, evaluate this | 3-stage gate: Mechanical → Semantic → Consensus |
ooo evolve | ooo evolve, evolutionary loop, iterate until converged | Evolutionary loop until Similarity ≥ 0.95 |
ooo unstuck | ooo unstuck, I'm stuck, think sideways, lateral thinking | Nine Minds lateral thinking personas |
ooo status | ooo status, am I drifting?, drift check | Drift detection + session tracking |
ooo ralph | ooo ralph, ralph-ooo, don't stop, must complete, keep going | Persistent loop until verified |
ooo setup | ooo setup | Register MCP server (one-time) |
ooo cancel | /ouroboros:cancel, /ralph-ooo:cancel | Save checkpoint and exit |
---
Phase 1: Interview — From Wonder to Ontology
Wonder → "How should I live?" → "What IS 'live'?" → Ontology — Socrates
The Socratic Interviewer asks questions until Ambiguity ≤ 0.2. This is the gate between vague desire and executable spec.
ooo interview "I want to build a task management CLI"Ambiguity Formula
Ambiguity = 1 − Σ(clarityᵢ × weightᵢ)
Greenfield: Goal(40%) + Constraint(30%) + Success(30%)
Brownfield: Goal(35%) + Constraint(25%) + Success(25%) + Context(15%)
Threshold: Ambiguity ≤ 0.2 → ready for SeedExample scoring:
Goal: 0.9 × 0.4 = 0.36 # "Build a CLI task manager" — clear
Constraint: 0.8 × 0.3 = 0.24 # "Python 3.14+, SQLite only" — defined
Success: 0.7 × 0.3 = 0.21 # "Tasks create/list/complete" — measurable
──────
Clarity = 0.81
Ambiguity = 1 − 0.81 = 0.19 ≤ 0.2 → ✓ Ready for SeedWhy 0.2? At 80% weighted clarity, remaining unknowns are small enough for code-level decisions to resolve. Above that threshold, you're still guessing at architecture.
---
Phase 2: Seed — Immutable Specification
ooo seedGenerates YAML spec locked from interview answers:
goal: Build a CLI task management tool
constraints:
- Python 3.14+
- No external database
- SQLite for persistence
acceptance_criteria:
- Tasks can be created with title and priority
- Tasks can be listed with status filter
- Tasks can be marked complete
ontology_schema:
name: TaskManager
fields:
- name: tasks
type: array
- name: title
type: string
- name: priority
type: enum[low, medium, high]
- name: status
type: enum[open, done]The seed is immutable. Once generated, it is the ground truth. Drift is measured against it.
---
Phase 3: Execute — Double Diamond Run
ooo run seed.yaml
ooo run # uses seed from conversation contextExecutes the four phases: 1. Discover — research existing patterns, constraints, precedents 2. Define — ontological clarity, edge cases, decision boundaries 3. Design — architecture, component breakdown, interface contracts 4. Deliver — implementation, tests, documentation
---
Phase 4: Evaluate — 3-Stage Verification Gate
ooo evaluate <session_id>| Stage | Cost | What It Checks |
|---|---|---|
| Mechanical | Free | Lint, build, tests, coverage, type checks |
| Semantic | Standard | AC compliance, goal alignment, drift score |
| Consensus | Frontier (optional) | Multi-model vote, majority ratio |
Drift Thresholds
| Score | Status | Action |
|---|---|---|
0.0 – 0.15 | Excellent | On track |
0.15 – 0.30 | Acceptable | Monitor closely |
0.30+ | Exceeded | Course correction required |
Drift = weighted deviation from seed across three axes: Goal(50%) + Constraint(30%) + Ontology(20%).
---
Phase 5: Evolve — Ontological Convergence
ooo evolve "build a task management CLI"
ooo evolve "topic" --no-execute # ontology-only fast modeFlow
Gen 1: Interview → Seed(O₁) → Execute → Evaluate
Gen 2: Wonder → Reflect → Seed(O₂) → Execute → Evaluate
Gen 3: Wonder → Reflect → Seed(O₃) → Execute → Evaluate
...until Similarity ≥ 0.95 or 30 generationsConvergence Formula
Similarity = 0.5 × name_overlap + 0.3 × type_match + 0.2 × exact_match
Threshold: Similarity ≥ 0.95 → CONVERGED
Gen 1: {Task, Priority, Status} → baseline
Gen 2: {Task, Priority, Status, DueDate} → similarity 0.78 → CONTINUE
Gen 3: {Task, Priority, Status, DueDate} → similarity 1.00 → CONVERGED ✓Stagnation Detection
| Signal | Condition | Response |
|---|---|---|
| Stagnation | Similarity ≥ 0.95 for 3 consecutive gens | Stop — converged |
| Oscillation | Gen N ≈ Gen N-2 (period-2 cycle) | Invoke contrarian persona |
| Repetitive feedback | ≥ 70% question overlap across 3 gens | Invoke researcher persona |
| Hard cap | 30 generations reached | Stop — safety valve |
---
Ralph — Persistent Loop Until Verified
ooo ralph "fix all failing tests"
ooo ralph "implement the payment module""The boulder never stops." Each failure is data for the next attempt. Only verified success or max iterations stops it.
Loop Architecture
┌─────────────────────────────────────┐
│ 1. EXECUTE (parallel agents) │
│ Fire independent sub-tasks │
│ concurrently via Agent tool │
├─────────────────────────────────────┤
│ 2. VERIFY │
│ Check acceptance criteria │
│ Run tests, lint, typecheck │
│ Measure drift vs seed │
├─────────────────────────────────────┤
│ 3. LOOP (if failed) │
│ Analyze failure evidence │
│ Fix identified issues │
│ Increment iteration counter │
│ Repeat from step 1 │
├─────────────────────────────────────┤
│ 4. PERSIST (each iteration) │
│ .omc/state/ralph-ooo-state.json │
│ Resume after interruption │
└─────────────────────────────────────┘State File Schema
Create .omc/state/ralph-ooo-state.json on start:
{
"mode": "ralph-ooo",
"session_id": "<uuid>",
"request": "<user request>",
"status": "running",
"iteration": 0,
"max_iterations": 10,
"last_checkpoint": null,
"seed_path": null,
"verification_history": []
}Loop Logic (Pseudocode)
while iteration < max_iterations:
result = execute_parallel(request, context)
verification = verify_result(result, acceptance_criteria)
state.verification_history.append({
"iteration": iteration,
"passed": verification.passed,
"score": verification.score,
"timestamp": now()
})
save_checkpoint(f"iteration_{iteration}")
if verification.passed:
save_checkpoint("complete")
break
iteration += 1Progress Report Format
[Ralph-OOO Iteration 1/10]
Executing in parallel...
Verification: FAILED
Score: 0.65
Issues:
- 3 tests still failing
- Type error in src/api.py:42
The boulder never stops. Continuing...
[Ralph-OOO Iteration 3/10]
Verification: PASSED ✓
Score: 1.0
Ralph-OOO COMPLETE
==================
Request: Fix all failing tests
Duration: 8m 32s
Iterations: 3
Verification History:
- Iteration 1: FAILED (0.65)
- Iteration 2: FAILED (0.85)
- Iteration 3: PASSED (1.0)Completion Promise (Codex / Gemini)
<promise>DONE</promise>Default promise: DONE | Default max iterations: 10
Cancellation
| Action | Command |
|---|---|
| Save checkpoint & exit | /ouroboros:cancel or /ralph-ooo:cancel |
| Force clear all state | /ouroboros:cancel --force |
| Resume after interruption | ooo ralph continue |
---
The Nine Minds
Loaded on-demand — never preloaded. Each mind has a single core question it cannot stop asking.
| Agent | Role | Core Question |
|---|---|---|
| Socratic Interviewer | Questions-only. Never builds. | "What are you assuming?" |
| Ontologist | Finds essence, not symptoms | "What IS this, really?" |
| Seed Architect | Crystallizes specs from dialogue | "Is this complete and unambiguous?" |
| Evaluator | 3-stage verification | "Did we build the right thing?" |
| Contrarian | Challenges every assumption | "What if the opposite were true?" |
| Hacker | Finds unconventional paths | "What constraints are actually real?" |
| Simplifier | Removes complexity | "What's the simplest thing that could work?" |
| Researcher | Stops coding, starts investigating | "What evidence do we actually have?" |
| Architect | Identifies structural causes | "If we started over, would we build it this way?" |
See references/nine-minds.md for full agent profiles.
---
Unstuck — Lateral Thinking
When blocked after repeated failures:
ooo unstuck # auto-select based on context
ooo unstuck simplifier # cut scope to MVP
ooo unstuck hacker # make it work first, elegance later
ooo unstuck contrarian # challenge all assumptions
ooo unstuck researcher # stop coding, find missing information
ooo unstuck architect # restructure the approach entirelyDecision guide:
- Repeated similar failures →
contrarian(challenge assumptions) - Too many options / paralysis →
simplifier(reduce scope) - Missing information / unclear root cause →
researcher(seek evidence) - Analysis paralysis / need momentum →
hacker(just make it work) - Structural issues / wrong foundation →
architect(redesign)
---
Quick Reference
| Action | Command |
|---|---|
| Socratic interview | ooo interview "topic" |
| Generate spec | ooo seed |
| Execute spec | ooo run [seed.yaml] |
| 3-stage evaluate | ooo evaluate <session_id> |
| Evolve until converged | ooo evolve "topic" |
| Persistent loop | ooo ralph "task" |
| Break stagnation | ooo unstuck [persona] |
| Check drift | ooo status [session_id] |
| First-time setup | ooo setup |
| Cancel | /ouroboros:cancel |
| Force cancel | /ouroboros:cancel --force |
| Resume | ooo ralph continue |
---
Available Scripts
Run from the skill directory:
| Script | Purpose |
|---|---|
scripts/setup-codex-hook.sh | Configure Codex CLI for ralph-ooo (developer_instructions + prompts) |
scripts/setup-gemini-hook.sh | Configure Gemini CLI AfterAgent hook for loop continuation |
scripts/ooo-state.sh | Manage .omc/state/ralph-ooo-state.json (init/status/checkpoint/reset/resume) |
---
Platform Support Matrix
| Platform | Support | Mechanism | ooo Commands | Auto Loop |
|---|---|---|---|---|
| Claude Code | Full | Skills system + hooks | All ooo commands | Via hooks |
| Codex CLI | Adapted | bash loop + /prompts:ralph-ooo | Via conversation | Manual state file |
| Gemini CLI | Native | AfterAgent hook | All ooo commands | Via hook |
| OpenCode | Native | Skills system | All ooo commands | Via loop |
---
Installation
# Claude Code (via oh-my-skills)
npx skills add https://github.com/akillness/oh-my-skills --skill ralph-ooo
# Codex CLI setup
bash .agent-skills/ralph-ooo/scripts/setup-codex-hook.sh
# Gemini CLI setup
bash .agent-skills/ralph-ooo/scripts/setup-gemini-hook.sh
# Ouroboros native plugin
claude plugin marketplace add Q00/ouroboros
claude plugin install ouroboros@ouroboros
ooo setup---
References
Detailed documentation in references/:
| File | Contents |
|---|---|
references/ouroboros-commands.md | Full ooo command syntax, parameters, output formats, state schemas |
references/nine-minds.md | All 9 agent profiles, core questions, when to invoke, unstuck guide |
references/platform-setup.md | Per-platform setup, hooks.json, AfterAgent config, Gemini bug workarounds |
---
Source: Q00/ouroboros — MIT License
The Nine Minds — Agent Profiles
Loaded on-demand — never preloaded. Each mind has a single core question it cannot stop asking.
>
Invoking the wrong mind is worse than invoking none. Match the agent to the situation.
---
Overview
| Agent | Invoked By | Core Question | Never Does |
|---|---|---|---|
| Socratic Interviewer | ooo interview | "What are you assuming?" | Builds anything |
| Ontologist | ooo seed (internal) | "What IS this, really?" | Accepts surface-level answers |
| Seed Architect | ooo seed | "Is this complete and unambiguous?" | Writes code |
| Evaluator | ooo evaluate | "Did we build the right thing?" | Provides vague opinions |
| Contrarian | ooo unstuck contrarian | "What if the opposite were true?" | Agrees with you |
| Hacker | ooo unstuck hacker | "What constraints are actually real?" | Cares about elegance |
| Simplifier | ooo unstuck simplifier | "What's the simplest thing that could work?" | Adds features |
| Researcher | ooo unstuck researcher | "What evidence do we actually have?" | Assumes anything |
| Architect | ooo unstuck architect | "If we started over, would we build it this way?" | Accepts the current structure |
---
1. Socratic Interviewer
Role: Questions-only. Never builds anything.
Core question: "What are you assuming?"
Behavior:
- Asks one focused question per turn
- Never suggests answers — questions only
- Scores ambiguity after each exchange
- Stops when Ambiguity ≤ 0.2
Example trigger phrases: ooo interview, interview me, clarify requirements, what should I build?
Sample questions it asks:
- "When you say 'user', do you mean an authenticated account or any visitor?"
- "What happens to existing data if someone upgrades from v1 to v2?"
- "How will you know this is 'done'? What does the demo look like?"
When NOT to use: After requirements are clear. The interviewer prolongs dialogue — skip it when you already have a spec.
---
2. Ontologist
Role: Finds the essence of things, not their symptoms.
Core question: "What IS this, really?"
Behavior:
- Deconstructs concepts to their fundamental nature
- Distinguishes root problems from surface manifestations
- Identifies undefined terms in requirements
- Builds the domain vocabulary
Example output:
Q: "I want to fix the auth bug."
Ontologist: "Is this a bug in authentication (who you are) or authorization (what you can do)?
Authentication: wrong password accepted, session hijacking, token expiry
Authorization: wrong permissions granted, scope creep
Which IS the bug?"When to use: When requirements contain undefined domain terms, or when the same word means different things to different stakeholders.
---
3. Seed Architect
Role: Crystallizes interview dialogue into a complete, unambiguous YAML specification.
Core question: "Is this complete and unambiguous?"
Behavior:
- Synthesizes interview answers into structured YAML
- Blocks generation if Ambiguity > 0.2
- Ensures acceptance criteria are measurable (not "works correctly")
- Defines the ontology schema explicitly
Output check:
- Every acceptance criterion must be verifiable by a test or human demo
- Every ontology field must have an explicit type
- Constraints must be specific (no "fast" or "scalable" without numbers)
---
4. Evaluator
Role: 3-stage verification judge.
Core question: "Did we build the right thing?"
Behavior:
- Stage 1 (Mechanical): runs tests, lint, build, type checks — no LLM
- Stage 2 (Semantic): checks AC compliance, goal alignment, drift score
- Stage 3 (Consensus): optional multi-model vote (majority ≥ 0.6 required)
- Reports drift score against the original seed
When to use: After ooo run completes, before claiming done.
---
5. Contrarian
Role: Challenges every assumption without mercy.
Core question: "What if the opposite were true?"
Behavior:
- Takes your strongest assumption and inverts it
- Does not propose solutions — only challenges
- Particularly effective for oscillating evolutionary loops
Example trigger: 3+ iterations with the same failure pattern.
Sample challenges:
- "You're assuming this needs to be a REST API. What if it's a message queue?"
- "You're optimizing for read speed. What if writes are the bottleneck?"
- "You're assuming users want this feature. What if they never asked for it?"
When to use: Repeated similar failures suggesting a wrong foundational assumption.
---
6. Hacker
Role: Makes things work by any means — elegance is irrelevant.
Core question: "What constraints are actually real?"
Behavior:
- Treats all constraints as negotiable until proven otherwise
- Finds the shortest path to working code
- Ignores best practices in service of demonstration
- "Make it work first; make it right later"
Example trigger: Analysis paralysis, too many architecture options, inability to start.
Sample output:
"Stop designing. Write the simplest version that could possibly work:
- No abstraction layers
- No error handling beyond the happy path
- Hardcode values if needed
Get it running, then refactor."When to use: When paralysis prevents any forward progress.
---
7. Simplifier
Role: Removes complexity until the minimum viable thing remains.
Core question: "What's the simplest thing that could work?"
Behavior:
- Identifies the single most critical feature
- Proposes cutting everything else
- Redefines scope to be demonstrable in one iteration
- "Start with exactly 2 tables. Not 5. Not 3. 2."
Example trigger: Feature creep, scope explosion, too many user stories.
When to use: When scope has grown beyond one iteration's capacity.
---
8. Researcher
Role: Stops coding and finds the missing information.
Core question: "What evidence do we actually have?"
Behavior:
- Identifies what is assumed vs. known
- Proposes specific information-gathering actions
- Refuses to proceed without evidence
- "We are building on quicksand. Find the solid ground first."
Example trigger: Repeated failures suggesting a wrong mental model of the system.
Sample output:
"Before writing more code:
1. Read the actual error logs (don't interpret them — read them)
2. Check what the API actually returns (not what docs say)
3. Find the git blame for this module
4. Ask the person who wrote this what it was supposed to do"When to use: When repeated failures suggest a factual misunderstanding.
---
9. Architect
Role: Identifies structural causes and proposes complete redesigns.
Core question: "If we started over, would we build it this way?"
Behavior:
- Diagnoses structural problems vs. surface bugs
- Proposes alternative architectures
- Does not patch — redesigns
- "The foundation is wrong. A different foundation fixes the whole problem."
Example trigger: Technical debt accumulation preventing forward progress.
When to use: When fixing one thing breaks another, repeatedly, across iterations.
---
Unstuck Decision Guide
Use this table when ooo unstuck is triggered without a specified persona:
| Situation | Best Persona | Why |
|---|---|---|
| Same failure 3+ times with same fix | contrarian | Wrong assumption driving wrong solution |
| Too many design options, can't choose | simplifier | Reduce to minimum viable choice |
| Unclear root cause, guessing fixes | researcher | Find evidence before acting |
| Can't start despite clear requirements | hacker | Remove perfect-is-enemy-of-good block |
| Fixing X breaks Y, repeatedly | architect | Wrong foundation, not wrong implementation |
| Requirements keep growing | simplifier + contrarian | Both scope and assumptions need cutting |
| Evolutionary loop oscillating | contrarian | Challenge the oscillating assumption |
| Ontology similarity plateauing below 0.95 | ontologist | Redefine the domain vocabulary |
Ouroboros Commands — Full Reference
Complete syntax, parameters, output formats, and state schemas for all ooo commands.---
ooo interview
Purpose: Socratic questioning to expose hidden assumptions before writing code.
Syntax:
ooo interview "topic"
ooo interview "topic" --brownfield # existing codebase contextWhat happens: 1. Agent: ouroboros:socratic-interviewer activates 2. Asks structured questions across all clarity dimensions 3. Scores ambiguity after each round 4. Continues until Ambiguity ≤ 0.2
Ambiguity Scoring
| Dimension | Greenfield | Brownfield | What it measures |
|---|---|---|---|
| Goal Clarity | 40% | 35% | Is the goal specific and bounded? |
| Constraint Clarity | 30% | 25% | Are limitations explicitly defined? |
| Success Criteria | 30% | 25% | Are outcomes measurable? |
| Context Clarity | — | 15% | Is the existing codebase understood? |
Formula:
Ambiguity = 1 − Σ(clarityᵢ × weightᵢ)
Example (Greenfield):
Goal: 0.9 × 0.4 = 0.36
Constraint: 0.8 × 0.3 = 0.24
Success: 0.7 × 0.3 = 0.21
──────
Clarity = 0.81
Ambiguity = 1 − 0.81 = 0.19 ≤ 0.2 → ✓ Ready for SeedScores are assigned by the LLM at temperature 0.1 for reproducibility.
---
ooo seed
Purpose: Crystallize interview answers into an immutable YAML specification.
Syntax:
ooo seed
ooo seed --output seed.yaml # explicit output pathRequires: Ambiguity ≤ 0.2 (blocks otherwise)
Output format:
goal: <specific goal from interview>
constraints:
- <constraint 1>
- <constraint 2>
acceptance_criteria:
- <measurable criterion 1>
- <measurable criterion 2>
ontology_schema:
name: <domain name>
fields:
- name: <field>
type: <type>Important: Once generated, the seed is immutable. All drift is measured against it.
---
ooo run
Purpose: Execute the seed specification via Double Diamond decomposition.
Syntax:
ooo run
ooo run seed.yaml
ooo run seed.yaml --skip-discover # skip research phasePhases:
| Phase | What Happens |
|---|---|
| Discover | Research existing patterns, constraints, precedents |
| Define | Ontological clarity, edge cases, decision boundaries |
| Design | Architecture, component breakdown, interface contracts |
| Deliver | Implementation, tests, documentation |
---
ooo evaluate
Purpose: 3-stage verification gate against seed acceptance criteria.
Syntax:
ooo evaluate <session_id>
ooo evaluate # evaluates most recent session
ooo evaluate --skip-consensus # skip frontier model stage3-Stage Gate
| Stage | Cost | What It Checks |
|---|---|---|
| Mechanical | Free | Lint, build, tests, coverage, type checks |
| Semantic | Standard | AC compliance, goal alignment, drift score |
| Consensus | Frontier (optional) | Multi-model vote, majority ratio ≥ 0.6 |
Drift Thresholds
| Score | Status | Meaning |
|---|---|---|
0.0 – 0.15 | Excellent | On track; no corrective action |
0.15 – 0.30 | Acceptable | Monitor closely; watch for creep |
0.30+ | Exceeded | Course correction required before continuing |
Drift formula: Goal(50%) + Constraint(30%) + Ontology(20%)
---
ooo evolve
Purpose: Evolutionary loop until ontology converges (Similarity ≥ 0.95).
Syntax:
ooo evolve "topic"
ooo evolve "topic" --no-execute # ontology-only fast mode
ooo evolve --status <lineage_id> # check lineage status
ooo evolve --rewind <lineage_id> <gen> # roll back to generation NConvergence Formula
Similarity = 0.5 × name_overlap + 0.3 × type_match + 0.2 × exact_match
Threshold: Similarity ≥ 0.95 → CONVERGEDStagnation Signals
| Signal | Condition | Response |
|---|---|---|
| Stagnation | Similarity ≥ 0.95 for 3 consecutive gens | Stop — converged |
| Oscillation | Gen N ≈ Gen N-2 | Invoke contrarian |
| Repetitive feedback | ≥ 70% question overlap across 3 gens | Invoke researcher |
| Hard cap | 30 generations reached | Stop — safety valve |
---
ooo ralph
Purpose: Persistent loop until verification passes — the boulder never stops.
Syntax:
ooo ralph "task"
ooo ralph "task" --max-iterations=15
ooo ralph "task" --completion-promise=VERIFIED
ooo ralph continue # resume from checkpointState File Schema
Location: .omc/state/ralph-ooo-state.json
{
"mode": "ralph-ooo",
"session_id": "uuid-v4",
"request": "original user request",
"status": "running | complete | failed | cancelled",
"iteration": 0,
"max_iterations": 10,
"last_checkpoint": null,
"seed_path": "path/to/seed.yaml or null",
"verification_history": [
{
"iteration": 1,
"passed": false,
"score": 0.65,
"issues": ["3 tests failing", "type error in api.py"],
"timestamp": "2026-03-23T12:00:00Z"
}
]
}Completion Promise
Codex and Gemini detect loop completion via XML in the output:
<promise>DONE</promise>- Default promise value:
DONE - Default max iterations:
10 - Custom promise:
--completion-promise=MY_SIGNAL
Progress Report Format
[Ralph-OOO Iteration N/max]
Executing in parallel...
Verification: FAILED | PASSED
Score: 0.0 – 1.0
Issues:
- <issue 1>
- <issue 2>
The boulder never stops. Continuing...---
ooo unstuck
Purpose: Activate a lateral thinking persona to break through stagnation.
Syntax:
ooo unstuck
ooo unstuck simplifier
ooo unstuck hacker
ooo unstuck contrarian
ooo unstuck researcher
ooo unstuck architectSee nine-minds.md for full agent profiles.
---
ooo status
Purpose: Drift detection and session health check.
Syntax:
ooo status
ooo status <session_id>Output:
Session: <id>
Iteration: 3/10
Drift Score: 0.18 (Acceptable)
Goal: 0.12
Constraint: 0.22
Ontology: 0.21
Last Checkpoint: iteration_3
Status: running---
ooo setup
Purpose: One-time MCP server registration.
ooo setupRequired before using ooo run, ooo evaluate, ooo evolve, ooo status. Adds Ouroboros reference block to project CLAUDE.md.
---
ooo cancel
Purpose: Clean exit from running loops.
/ouroboros:cancel # save checkpoint, exit cleanly
/ouroboros:cancel --force # clear all state, force exit
/ralph-ooo:cancel # alias
ooo cancel # within conversation---
Codex-Specific: ralph loop contract
/ralph "task" [--completion-promise=TEXT] [--max-iterations=N]1. Keep original task unchanged across all retries 2. Detect completion: <promise>VALUE</promise> in output 3. If promise missing and iteration < max → continue immediately 4. If promise found or max reached → finish with status report 5. State file updated each iteration at .omc/state/ralph-ooo-state.json
Platform Setup Guide
Multi-platform configuration for ralph-ooo on Claude Code, Codex CLI, Gemini CLI, and OpenCode.
---
Platform Support Matrix
| Platform | Support Level | Mechanism | ooo Commands | Auto Loop |
|---|---|---|---|---|
| Claude Code | Full | Skills system + UserPromptSubmit hook | All ooo commands | Via hooks |
| Codex CLI | Adapted | bash loop + /prompts:ralph-ooo | Via conversation | Manual state file |
| Gemini CLI | Native | AfterAgent hook | All ooo commands | Via hook |
| OpenCode | Native | Skills system | All ooo commands | Via loop |
---
Claude Code (Full Mode)
Option A: Ouroboros native plugin
# Install
claude plugin marketplace add Q00/ouroboros
claude plugin install ouroboros@ouroboros
# One-time setup (inside Claude Code session)
ooo setupOption B: oh-my-skills integration
npx skills add https://github.com/akillness/oh-my-skills --skill ralph-oooHooks
Claude Code hooks auto-activate on install. Configured at ${CLAUDE_PLUGIN_ROOT}/hooks/hooks.json:
{
"hooks": {
"SessionStart": [{
"matcher": "*",
"hooks": [{
"type": "command",
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/session-start.mjs\"",
"timeout": 5
}]
}],
"UserPromptSubmit": [{
"matcher": "*",
"hooks": [{
"type": "command",
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/keyword-detector.mjs\"",
"timeout": 5
}]
}],
"PostToolUse": [{
"matcher": "Write|Edit",
"hooks": [{
"type": "command",
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/drift-monitor.mjs\"",
"timeout": 3
}]
}]
}
}Hook behaviors:
SessionStart→ initializes session stateUserPromptSubmit→ keyword-detector triggersooocommands automaticallyPostToolUse(Write|Edit)→ drift-monitor tracks deviation from seed
Usage
ooo interview "I want to build a task CLI"
ooo seed
ooo run
ooo evaluate <session_id>
ooo ralph "fix all failing tests"---
Codex CLI (Adapted Mode)
Codex CLI has no native AfterAgent hooks. Ralph loop uses conversation-level promise detection.
Setup
bash .agent-skills/ralph-ooo/scripts/setup-codex-hook.shThis configures: 1. ~/.codex/config.toml — adds developer_instructions with ooo command contract 2. ~/.codex/prompts/ralph-ooo.md — load via /prompts:ralph-ooo 3. ~/.codex/prompts/ouroboros.md — load via /prompts:ouroboros
Manual config.toml
developer_instructions = """
Ouroboros specification-first workflow active. ooo command contract:
COMMANDS:
ooo interview [topic] - Socratic questioning until Ambiguity≤0.2
ooo seed - Crystallize into immutable YAML spec
ooo run [seed.yaml] - Execute via Double Diamond
ooo evaluate <id> - 3-stage: Mechanical→Semantic→Consensus
ooo evolve [topic] - Evolutionary loop until Similarity≥0.95
ooo unstuck [persona] - Lateral thinking
ooo status [id] - Drift check
ooo ralph "task" - Persistent loop until verified
RALPH LOOP CONTRACT:
/ralph "<task>" [--completion-promise=TEXT] [--max-iterations=N]
Signal: <promise>DONE</promise>
Default promise: DONE. Default max: 10.
State: .omc/state/ralph-ooo-state.json
The boulder never stops.
"""Usage
# Start Codex
codex
# Load ralph-ooo context
/prompts:ralph-ooo
# Start ralph loop
/ralph "fix all TypeScript errors" --max-iterations=10Ralph loop contract (Codex)
1. Treat /ralph "<task>" as a binding contract command 2. Keep original task unchanged across all retries 3. Detect completion: <promise>DONE</promise> in output 4. If promise missing and iteration < max → continue immediately 5. If promise found or max reached → finish with status report 6. Update .omc/state/ralph-ooo-state.json each iteration
High-autonomy mode
For sandbox environments only:
codex --dangerously-bypass-approvals-and-sandbox \
-c model_reasoning_effort="high" \
-c model_reasoning_summary="detailed"---
Gemini CLI (AfterAgent Hook Mode)
Install via extensions
gemini extensions install https://github.com/Q00/ouroborosOr use setup script:
bash .agent-skills/ralph-ooo/scripts/setup-gemini-hook.shRequired settings.json
Add to ~/.gemini/settings.json:
{
"hooksConfig": { "enabled": true },
"context": {
"includeDirectories": ["~/.gemini/extensions/ralph-ooo"]
},
"hooks": {
"AfterAgent": [{
"matcher": "*",
"hooks": [{
"type": "command",
"command": "bash ~/.gemini/hooks/ralph-ooo-check.sh",
"timeout": 10
}]
}]
}
}Ralph-ooo AfterAgent hook script
Location: ~/.gemini/hooks/ralph-ooo-check.sh
#!/usr/bin/env bash
# Reads .omc/state/ralph-ooo-state.json to decide whether to continue the loop.
# Workaround for Gemini v0.30.0 bug: stop_hook_active is always false in hook JSON.
STATE_FILE=".omc/state/ralph-ooo-state.json"
if [ ! -f "$STATE_FILE" ]; then
exit 0
fi
STATUS=$(python3 -c "import json,sys; d=json.load(open('$STATE_FILE')); print(d.get('status',''))")
ITER=$(python3 -c "import json,sys; d=json.load(open('$STATE_FILE')); print(d.get('iteration',0))")
MAX=$(python3 -c "import json,sys; d=json.load(open('$STATE_FILE')); print(d.get('max_iterations',10))")
if [ "$STATUS" = "complete" ] || [ "$STATUS" = "cancelled" ]; then
exit 0
fi
if [ "$ITER" -ge "$MAX" ]; then
exit 0
fi
# Inject continuation prompt
echo "CONTINUE_RALPH: Ralph-OOO iteration $ITER/$MAX still running. Continue with ooo ralph loop."
exit 1 # non-zero exit re-triggers agent⚠️ Gemini v0.30.0 Bug
stop_hook_active is always false in hook JSON. Do not rely on it.
Workaround: read .omc/state/ralph-ooo-state.json directly to determine loop state.
Recommended Gemini run mode
gemini -s -y # sandbox + YOLO (no confirmation prompts)---
OpenCode
OpenCode natively supports the skills system. No additional setup required.
{
"$schema": "https://opencode.ai/config.json",
"instructions": "Use ooo commands for specification-first development. ooo interview to start."
}Skills auto-load from the .agent-skills/ directory.
---
State File Location
Across all platforms, ralph-ooo state lives at:
.omc/state/ralph-ooo-state.jsonUse the state utility script to manage it:
bash .agent-skills/ralph-ooo/scripts/ooo-state.sh init "fix all tests"
bash .agent-skills/ralph-ooo/scripts/ooo-state.sh status
bash .agent-skills/ralph-ooo/scripts/ooo-state.sh checkpoint
bash .agent-skills/ralph-ooo/scripts/ooo-state.sh reset
bash .agent-skills/ralph-ooo/scripts/ooo-state.sh resume#!/usr/bin/env bash
# ooo-state.sh — ralph-ooo state file manager
#
# Manages .omc/state/ralph-ooo-state.json for the ralph-ooo persistent loop.
#
# Usage:
# bash ooo-state.sh <subcommand> [args]
#
# Subcommands:
# init <request> [max_iterations] Create a new state file
# status Print current state summary
# checkpoint [note] Increment iteration counter
# reset Clear state file (sets status: cancelled)
# resume Print resume instructions
# history Print verification history
set -euo pipefail
STATE_DIR=".omc/state"
STATE_FILE="$STATE_DIR/ralph-ooo-state.json"
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
GRAY='\033[0;37m'
CYAN='\033[0;36m'
NC='\033[0m'
# ── Helpers ──────────────────────────────────────────────────────────────────
require_python() {
if ! command -v python3 &>/dev/null; then
echo -e "${RED}✗ python3 required but not found${NC}" >&2
exit 1
fi
}
require_state() {
if [ ! -f "$STATE_FILE" ]; then
echo -e "${RED}✗ No state file at ${STATE_FILE}${NC}" >&2
echo -e "${GRAY} Run: bash ooo-state.sh init \"your task\"${NC}" >&2
exit 1
fi
}
generate_uuid() {
if command -v python3 &>/dev/null; then
python3 -c "import uuid; print(str(uuid.uuid4()))"
elif command -v uuidgen &>/dev/null; then
uuidgen | tr '[:upper:]' '[:lower:]'
else
echo "$(date +%s)-$$-$(od -An -N4 -tx4 /dev/urandom 2>/dev/null | tr -d ' ' || echo 'rand')"
fi
}
now_iso() {
date -u +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || date +"%Y-%m-%dT%H:%M:%SZ"
}
# ── Subcommands ───────────────────────────────────────────────────────────────
cmd_init() {
local request="${1:-unnamed task}"
local max_iter="${2:-10}"
local session_id
session_id="$(generate_uuid)"
local timestamp
timestamp="$(now_iso)"
require_python
mkdir -p "$STATE_DIR"
python3 - "$STATE_FILE" "$session_id" "$request" "$max_iter" "$timestamp" <<'PYEOF'
import json, sys
path, sid, req, max_it, ts = sys.argv[1], sys.argv[2], sys.argv[3], int(sys.argv[4]), sys.argv[5]
state = {
"mode": "ralph-ooo",
"session_id": sid,
"request": req,
"status": "running",
"iteration": 0,
"max_iterations": max_it,
"last_checkpoint": None,
"seed_path": None,
"created_at": ts,
"updated_at": ts,
"verification_history": []
}
with open(path, "w") as f:
json.dump(state, f, indent=2)
f.write("\n")
print(f"session_id: {sid}")
PYEOF
echo ""
echo -e "${GREEN}✓ State file initialized: ${STATE_FILE}${NC}"
echo -e " session_id: $(python3 -c "import json; d=json.load(open('$STATE_FILE')); print(d['session_id'])")"
echo -e " request: ${request}"
echo -e " max_iterations: ${max_iter}"
echo -e " status: running"
echo ""
}
cmd_status() {
require_state
require_python
python3 - "$STATE_FILE" <<'PYEOF'
import json, sys
with open(sys.argv[1]) as f:
d = json.load(f)
status = d.get("status", "unknown")
color = {
"running": "\033[0;33m",
"complete": "\033[0;32m",
"failed": "\033[0;31m",
"cancelled": "\033[0;37m"
}.get(status, "\033[0m")
NC = "\033[0m"
print(f"\n{color}Status: {status}{NC}")
print(f" Session: {d.get('session_id', 'N/A')}")
print(f" Request: {d.get('request', 'N/A')}")
print(f" Iteration: {d.get('iteration', 0)} / {d.get('max_iterations', 10)}")
print(f" Checkpoint: {d.get('last_checkpoint', 'none')}")
print(f" Seed: {d.get('seed_path', 'none')}")
history = d.get("verification_history", [])
if history:
print(f"\n Verification history ({len(history)} entries):")
for h in history[-5:]: # last 5
marker = "✓" if h.get("passed") else "✗"
score = h.get("score", "?")
print(f" [{marker}] Iter {h.get('iteration', '?')}: score={score}")
print()
PYEOF
}
cmd_checkpoint() {
require_state
require_python
local note="${1:-}"
local timestamp
timestamp="$(now_iso)"
python3 - "$STATE_FILE" "$timestamp" "$note" <<'PYEOF'
import json, sys
path, ts, note = sys.argv[1], sys.argv[2], sys.argv[3]
with open(path) as f:
d = json.load(f)
old_iter = d.get("iteration", 0)
d["iteration"] = old_iter + 1
d["last_checkpoint"] = f"iteration_{d['iteration']}"
d["updated_at"] = ts
with open(path, "w") as f:
json.dump(d, f, indent=2)
f.write("\n")
print(f"Iteration {old_iter} → {d['iteration']} (checkpoint: {d['last_checkpoint']})")
PYEOF
echo -e "${GREEN}✓ Checkpoint saved: iteration $(python3 -c "import json; d=json.load(open('$STATE_FILE')); print(d['iteration'])")${NC}"
}
cmd_complete() {
require_state
require_python
local timestamp
timestamp="$(now_iso)"
python3 - "$STATE_FILE" "$timestamp" <<'PYEOF'
import json, sys
path, ts = sys.argv[1], sys.argv[2]
with open(path) as f:
d = json.load(f)
d["status"] = "complete"
d["last_checkpoint"] = "complete"
d["updated_at"] = ts
with open(path, "w") as f:
json.dump(d, f, indent=2)
f.write("\n")
print(f"Marked complete at iteration {d.get('iteration', 0)}")
PYEOF
echo -e "${GREEN}✓ State marked complete${NC}"
}
cmd_reset() {
if [ ! -f "$STATE_FILE" ]; then
echo -e "${YELLOW}⚠ No state file to reset${NC}"
exit 0
fi
require_python
local timestamp
timestamp="$(now_iso)"
python3 - "$STATE_FILE" "$timestamp" <<'PYEOF'
import json, sys
path, ts = sys.argv[1], sys.argv[2]
with open(path) as f:
d = json.load(f)
d["status"] = "cancelled"
d["last_checkpoint"] = "cancelled"
d["updated_at"] = ts
with open(path, "w") as f:
json.dump(d, f, indent=2)
f.write("\n")
print("State reset (status: cancelled)")
PYEOF
echo -e "${YELLOW}✓ State reset (status: cancelled)${NC}"
echo -e "${GRAY} File kept at ${STATE_FILE} — run 'init' to start fresh${NC}"
}
cmd_resume() {
require_state
require_python
local session_id iter max_iter request status
session_id="$(python3 -c "import json; d=json.load(open('$STATE_FILE')); print(d.get('session_id','?'))")"
iter="$(python3 -c "import json; d=json.load(open('$STATE_FILE')); print(d.get('iteration',0))")"
max_iter="$(python3 -c "import json; d=json.load(open('$STATE_FILE')); print(d.get('max_iterations',10))")"
request="$(python3 -c "import json; d=json.load(open('$STATE_FILE')); print(d.get('request','?'))")"
status="$(python3 -c "import json; d=json.load(open('$STATE_FILE')); print(d.get('status','?'))")"
echo ""
echo -e "${CYAN}ralph-ooo Resume Instructions${NC}"
echo -e "══════════════════════════════"
echo -e " Session: ${session_id}"
echo -e " Request: ${request}"
echo -e " Iteration: ${iter}/${max_iter}"
echo -e " Status: ${status}"
echo ""
echo -e "${BLUE}To resume, say one of:${NC}"
echo -e " ooo ralph continue"
echo -e " ooo ralph continue --session-id=${session_id}"
echo -e " /ralph \"${request}\" --max-iterations=${max_iter}"
echo ""
}
cmd_history() {
require_state
require_python
python3 - "$STATE_FILE" <<'PYEOF'
import json, sys
with open(sys.argv[1]) as f:
d = json.load(f)
history = d.get("verification_history", [])
if not history:
print("No verification history yet.")
sys.exit(0)
print(f"\nVerification History ({len(history)} entries):")
print("─" * 50)
for h in history:
marker = "PASS ✓" if h.get("passed") else "FAIL ✗"
score = h.get("score", "?")
itr = h.get("iteration", "?")
ts = h.get("timestamp", "?")
issues = h.get("issues", [])
print(f" Iteration {itr}: {marker} (score={score}) [{ts}]")
for issue in issues:
print(f" - {issue}")
print()
PYEOF
}
# ── Dispatch ──────────────────────────────────────────────────────────────────
SUBCOMMAND="${1:-help}"
shift || true
case "$SUBCOMMAND" in
init) cmd_init "$@" ;;
status) cmd_status ;;
checkpoint) cmd_checkpoint "${1:-}" ;;
complete) cmd_complete ;;
reset) cmd_reset ;;
resume) cmd_resume ;;
history) cmd_history ;;
help|--help|-h)
echo ""
echo -e "${BLUE}ooo-state.sh — ralph-ooo state manager${NC}"
echo ""
echo "Usage: bash ooo-state.sh <subcommand> [args]"
echo ""
echo "Subcommands:"
echo " init <request> [max] Create new state file (default max: 10)"
echo " status Print current state summary"
echo " checkpoint [note] Increment iteration counter + save checkpoint"
echo " complete Mark loop as complete"
echo " reset Set status to cancelled (keeps file)"
echo " resume Print resume instructions"
echo " history Print full verification history"
echo ""
echo "State file: ${STATE_FILE}"
echo ""
;;
*)
echo -e "${RED}Unknown subcommand: ${SUBCOMMAND}${NC}" >&2
echo "Run: bash ooo-state.sh help" >&2
exit 1
;;
esac
#!/usr/bin/env bash
# ralph-ooo (Ouroboros) - Codex CLI setup helper
# Configures Codex for the full Ouroboros specification-first workflow:
#
# 1) developer_instructions → ~/.codex/config.toml
# 2) ~/.codex/prompts/ralph-ooo.md (load via /prompts:ralph-ooo)
# 3) ~/.codex/prompts/ouroboros.md (load via /prompts:ouroboros)
#
# Usage:
# bash setup-codex-hook.sh [--dry-run] [--help]
set -euo pipefail
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
GRAY='\033[0;37m'
NC='\033[0m'
DRY_RUN=false
for arg in "$@"; do
case "$arg" in
--dry-run) DRY_RUN=true ;;
-h|--help)
echo "Usage: $0 [--dry-run]"
echo ""
echo "Configures Codex CLI for ralph-ooo / Ouroboros workflows:"
echo " 1. Adds ooo command contract to ~/.codex/config.toml developer_instructions"
echo " 2. Creates ~/.codex/prompts/ralph-ooo.md (load via /prompts:ralph-ooo)"
echo " 3. Creates ~/.codex/prompts/ouroboros.md (load via /prompts:ouroboros)"
echo ""
echo "Options:"
echo " --dry-run Show what would change without writing"
echo " -h, --help Show this help"
exit 0
;;
*) ;;
esac
done
CODEX_DIR="$HOME/.codex"
CODEX_CONFIG="$CODEX_DIR/config.toml"
CODEX_PROMPTS="$CODEX_DIR/prompts"
RALPH_OOO_PROMPT="$CODEX_PROMPTS/ralph-ooo.md"
OUROBOROS_PROMPT="$CODEX_PROMPTS/ouroboros.md"
echo ""
echo -e "${BLUE}╔════════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ ralph-ooo × Codex setup ║${NC}"
echo -e "${BLUE}║ Stop prompting. Start specifying. ║${NC}"
echo -e "${BLUE}╚════════════════════════════════════════════════╝${NC}"
echo ""
if ! command -v codex &>/dev/null; then
echo -e "${YELLOW}⚠ codex CLI not found in PATH${NC}"
echo -e "${GRAY} Install via: npm install -g @openai/codex${NC}"
echo -e "${GRAY} Continuing setup anyway (config and prompts will be prepared).${NC}"
echo ""
fi
mkdir -p "$CODEX_DIR" "$CODEX_PROMPTS"
# ── developer_instructions ──────────────────────────────────────────────────
OOO_INSTRUCTION='ralph-ooo / Ouroboros specification-first workflow active.
COMMANDS:
ooo interview [topic] - Socratic questioning until Ambiguity<=0.2
ooo seed - Crystallize into immutable YAML spec
ooo run [seed.yaml] - Execute via Double Diamond (Discover/Define/Design/Deliver)
ooo evaluate <id> - 3-stage: Mechanical->Semantic->Consensus; drift threshold<=0.3
ooo evolve [topic] - Evolutionary loop until Similarity>=0.95 or 30 generations
ooo unstuck [persona] - Lateral thinking: simplifier|hacker|contrarian|researcher|architect
ooo status [id] - Drift check: Goal(50%)+Constraint(30%)+Ontology(20%)
ooo ralph "task" - Persistent loop until verified; boulder never stops
RALPH LOOP CONTRACT:
/ralph "<task>" [--completion-promise=TEXT] [--max-iterations=N]
1) Keep original task unchanged across all retries
2) Detect completion: <promise>DONE</promise> in output
3) If promise missing and iteration < max: continue immediately
4) Default promise: DONE. Default max: 10.
5) State file: .omc/state/ralph-ooo-state.json (updated each iteration)
AMBIGUITY GATE: Ambiguity = 1 - SUM(clarity_i x weight_i) must be <=0.2 before seed
CONVERGENCE: Similarity = 0.5*name_overlap + 0.3*type_match + 0.2*exact_match >= 0.95'
# ── Step 1: config.toml ──────────────────────────────────────────────────────
echo -e "${BLUE}Step 1: config.toml developer_instructions${NC}"
if [ -f "$CODEX_CONFIG" ] && grep -q "ralph-ooo\|ooo interview\|ouroboros" "$CODEX_CONFIG" 2>/dev/null; then
echo -e "${YELLOW}⚠ developer_instructions already contains ralph-ooo/Ouroboros reference${NC}"
echo -e "${GRAY} No changes made to config.toml.${NC}"
else
if [ "$DRY_RUN" = true ]; then
echo -e "${YELLOW}[DRY RUN] Would add ralph-ooo ooo contract to developer_instructions in ${CODEX_CONFIG}${NC}"
else
if [ -f "$CODEX_CONFIG" ] && grep -q "^developer_instructions" "$CODEX_CONFIG" 2>/dev/null; then
if command -v python3 &>/dev/null; then
python3 - "$CODEX_CONFIG" "$OOO_INSTRUCTION" <<'PYEOF'
import sys, re
path, addition = sys.argv[1], sys.argv[2]
def escape_toml(v):
return v.replace("\\", "\\\\").replace('"', '\\"')
with open(path) as f:
content = f.read()
pattern = re.compile(r'^(developer_instructions\s*=\s*")(.+?)(")', re.MULTILINE | re.DOTALL)
match = pattern.search(content)
if match:
current = match.group(2)
if "ralph-ooo" not in current and "ooo interview" not in current:
new_val = current + " " + addition
content = (content[:match.start()]
+ f'developer_instructions = "{escape_toml(new_val)}"'
+ content[match.end():])
with open(path, "w") as out:
out.write(content)
print("Updated existing developer_instructions.")
else:
print("developer_instructions already includes ralph-ooo contract.")
else:
with open(path, "a") as out:
out.write(f'\ndeveloper_instructions = "{escape_toml(addition)}"\n')
print("Appended developer_instructions.")
PYEOF
else
printf '\ndeveloper_instructions = "%s"\n' "$OOO_INSTRUCTION" >> "$CODEX_CONFIG"
fi
else
printf 'developer_instructions = "%s"\n' "$OOO_INSTRUCTION" > "$CODEX_CONFIG"
fi
echo -e "${GREEN}✓ Updated ${CODEX_CONFIG}${NC}"
fi
fi
# ── Step 2: ralph-ooo prompt ─────────────────────────────────────────────────
echo ""
echo -e "${BLUE}Step 2: ralph-ooo prompt file (${RALPH_OOO_PROMPT})${NC}"
RALPH_OOO_CONTENT='# ralph-ooo — Ouroboros Completion Loop
The boulder never stops. This prompt configures Codex for ralph-ooo loop execution.
## Loop Contract
```
/ralph "task" [--completion-promise=TEXT] [--max-iterations=N]
```
1. Keep original task unchanged across all retries
2. Completion detected as: `<promise>DONE</promise>` in output
3. If not found and iteration < max → continue immediately
4. Default promise: `DONE` | Default max iterations: `10`
## State File
Create `.omc/state/ralph-ooo-state.json` at loop start:
```json
{
"mode": "ralph-ooo",
"session_id": "<uuid>",
"request": "<original request>",
"status": "running",
"iteration": 0,
"max_iterations": 10,
"last_checkpoint": null,
"seed_path": null,
"verification_history": []
}
```
## Progress Report Format
```
[Ralph-OOO Iteration N/max]
Executing in parallel...
Verification: FAILED | PASSED
Score: 0.0 – 1.0
Issues:
- <issue 1>
The boulder never stops. Continuing...
```
## Completion
```
<promise>DONE</promise>
Ralph-OOO COMPLETE
==================
Request: <original>
Duration: <time>
Iterations: <count>
```
## Full ooo Workflow
```
ooo interview "topic" → Socratic interview (Ambiguity≤0.2)
ooo seed → Generate spec
ooo run [seed.yaml] → Execute spec
ooo evaluate <id> → 3-stage verification
ooo evolve "topic" → Evolutionary loop (Similarity≥0.95)
ooo unstuck [persona] → Lateral thinking
ooo ralph "task" → Persistent loop
```
See /prompts:ouroboros for the complete Ouroboros reference.
'
if [ -f "$RALPH_OOO_PROMPT" ]; then
echo -e "${YELLOW}⚠ ${RALPH_OOO_PROMPT} already exists — overwriting${NC}"
fi
if [ "$DRY_RUN" = true ]; then
echo -e "${YELLOW}[DRY RUN] Would create/update ${RALPH_OOO_PROMPT}${NC}"
else
printf '%s\n' "$RALPH_OOO_CONTENT" > "$RALPH_OOO_PROMPT"
echo -e "${GREEN}✓ Created ${RALPH_OOO_PROMPT}${NC}"
fi
# ── Step 3: ouroboros prompt ─────────────────────────────────────────────────
echo ""
echo -e "${BLUE}Step 3: ouroboros prompt file (${OUROBOROS_PROMPT})${NC}"
OUROBOROS_CONTENT='# Ouroboros — Specification-First AI Development
> Stop prompting. Start specifying.
> The serpent does not repeat — it evolves.
## The Loop
```
Interview → Seed → Execute → Evaluate
↑ ↓
└──── Evolutionary Loop ────┘
```
## Commands
| Command | What It Does |
|---------|--------------|
| `ooo interview "topic"` | Socratic questioning → Ambiguity≤0.2 |
| `ooo seed` | Crystallize into immutable YAML spec |
| `ooo run [seed.yaml]` | Execute via Double Diamond |
| `ooo evaluate <id>` | 3-stage: Mechanical→Semantic→Consensus |
| `ooo evolve "topic"` | Evolutionary loop → Similarity≥0.95 |
| `ooo unstuck [persona]` | Lateral thinking: simplifier|hacker|contrarian|researcher|architect |
| `ooo status [id]` | Drift check (threshold ≤ 0.3) |
| `ooo ralph "task"` | Persistent loop until verified |
## Ambiguity Gate
```
Ambiguity = 1 − Σ(clarityᵢ × weightᵢ)
Greenfield: Goal(40%) + Constraint(30%) + Success(30%)
Brownfield: Goal(35%) + Constraint(25%) + Success(25%) + Context(15%)
Threshold: ≤ 0.2 → ready for Seed
```
## Convergence Gate
```
Similarity = 0.5×name_overlap + 0.3×type_match + 0.2×exact_match
Threshold: ≥ 0.95 → CONVERGED → loop stops
```
## Nine Minds (On-Demand)
socratic-interviewer | ontologist | seed-architect | evaluator |
contrarian | hacker | simplifier | researcher | architect
## Cancellation
- `/ouroboros:cancel` — save checkpoint, exit
- `/ouroboros:cancel --force` — clear all state
- `/ralph-ooo:cancel` — alias
- `ooo ralph continue` — resume from checkpoint
Source: https://github.com/Q00/ouroboros — MIT License
'
if [ -f "$OUROBOROS_PROMPT" ]; then
echo -e "${YELLOW}⚠ ${OUROBOROS_PROMPT} already exists — overwriting${NC}"
fi
if [ "$DRY_RUN" = true ]; then
echo -e "${YELLOW}[DRY RUN] Would create/update ${OUROBOROS_PROMPT}${NC}"
else
printf '%s\n' "$OUROBOROS_CONTENT" > "$OUROBOROS_PROMPT"
echo -e "${GREEN}✓ Created ${OUROBOROS_PROMPT}${NC}"
fi
# ── Summary ───────────────────────────────────────────────────────────────────
echo ""
echo -e "${GREEN}ralph-ooo × Codex setup complete.${NC}"
echo ""
echo -e "${BLUE}Next steps:${NC}"
echo -e " 1. Restart Codex session"
echo -e " 2. Load ralph-ooo context: ${GREEN}/prompts:ralph-ooo${NC}"
echo -e " 3. Load full reference: ${GREEN}/prompts:ouroboros${NC}"
echo -e " 4. Start specification: ${GREEN}ooo interview \"your idea\"${NC}"
echo -e " 5. Start persistent loop: ${GREEN}/ralph \"your task\" --max-iterations=10${NC}"
echo ""
echo -e "${GRAY}Note: Codex has no native AfterAgent hooks.${NC}"
echo -e "${GRAY}Ralph loop relies on <promise>DONE</promise> detection.${NC}"
echo ""
#!/usr/bin/env bash
# ralph-ooo (Ouroboros) - Gemini CLI AfterAgent hook setup
#
# Configures Gemini CLI to run the ralph-ooo loop continuation hook after each agent turn.
#
# What it does:
# 1) Creates ~/.gemini/hooks/ralph-ooo-check.sh (AfterAgent hook script)
# 2) Patches ~/.gemini/settings.json with the AfterAgent hook entry
# 3) Creates ~/.gemini/extensions/ralph-ooo/ context directory
#
# ⚠️ Gemini v0.30.0 bug: stop_hook_active is always false in hook JSON.
# This script uses direct state file reading as workaround.
#
# Usage:
# bash setup-gemini-hook.sh [--dry-run] [--help]
set -euo pipefail
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
GRAY='\033[0;37m'
NC='\033[0m'
DRY_RUN=false
for arg in "$@"; do
case "$arg" in
--dry-run) DRY_RUN=true ;;
-h|--help)
echo "Usage: $0 [--dry-run]"
echo ""
echo "Configures Gemini CLI for ralph-ooo loop continuation:"
echo " 1. Creates ~/.gemini/hooks/ralph-ooo-check.sh (AfterAgent hook)"
echo " 2. Patches ~/.gemini/settings.json (adds AfterAgent hook entry)"
echo " 3. Creates ~/.gemini/extensions/ralph-ooo/ (context directory)"
echo ""
echo "After setup, run Gemini with:"
echo " gemini -s -y # sandbox + YOLO mode (no confirmation prompts)"
echo ""
echo "NOTE: Gemini v0.30.0 bug — stop_hook_active always false."
echo " This script reads .omc/state/ralph-ooo-state.json directly."
echo ""
echo "Options:"
echo " --dry-run Show what would change without writing"
echo " -h, --help Show this help"
exit 0
;;
*) ;;
esac
done
GEMINI_DIR="$HOME/.gemini"
GEMINI_SETTINGS="$GEMINI_DIR/settings.json"
GEMINI_HOOKS="$GEMINI_DIR/hooks"
GEMINI_EXT="$GEMINI_DIR/extensions/ralph-ooo"
HOOK_SCRIPT="$GEMINI_HOOKS/ralph-ooo-check.sh"
echo ""
echo -e "${BLUE}╔════════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ ralph-ooo × Gemini CLI setup ║${NC}"
echo -e "${BLUE}║ AfterAgent hook for loop continuation ║${NC}"
echo -e "${BLUE}╚════════════════════════════════════════════════╝${NC}"
echo ""
if ! command -v gemini &>/dev/null; then
echo -e "${YELLOW}⚠ gemini CLI not found in PATH${NC}"
echo -e "${GRAY} Install: npm install -g @google/generative-ai-cli${NC}"
echo -e "${GRAY} Continuing setup anyway.${NC}"
echo ""
fi
mkdir -p "$GEMINI_DIR" "$GEMINI_HOOKS" "$GEMINI_EXT"
# ── Step 1: AfterAgent hook script ───────────────────────────────────────────
echo -e "${BLUE}Step 1: AfterAgent hook script (${HOOK_SCRIPT})${NC}"
HOOK_CONTENT='#!/usr/bin/env bash
# ralph-ooo AfterAgent hook for Gemini CLI
#
# Reads .omc/state/ralph-ooo-state.json to decide whether to continue the loop.
# Workaround for Gemini v0.30.0 bug: stop_hook_active is always false in hook JSON.
# We read the state file directly instead of relying on the hook field.
#
# Exit 0 → agent stops (loop complete or not running)
# Exit 1 → agent continues (loop still running)
STATE_FILE=".omc/state/ralph-ooo-state.json"
# Not running ralph-ooo
if [ ! -f "$STATE_FILE" ]; then
exit 0
fi
if ! command -v python3 &>/dev/null; then
exit 0
fi
STATUS=$(python3 -c "
import json, sys
try:
with open(\"$STATE_FILE\") as f:
d = json.load(f)
print(d.get(\"status\", \"\"))
except Exception:
print(\"\")
")
ITER=$(python3 -c "
import json, sys
try:
with open(\"$STATE_FILE\") as f:
d = json.load(f)
print(d.get(\"iteration\", 0))
except Exception:
print(0)
")
MAX=$(python3 -c "
import json, sys
try:
with open(\"$STATE_FILE\") as f:
d = json.load(f)
print(d.get(\"max_iterations\", 10))
except Exception:
print(10)
")
# Loop is done
if [ "$STATUS" = "complete" ] || [ "$STATUS" = "cancelled" ] || [ "$STATUS" = "failed" ]; then
exit 0
fi
# Iteration cap reached
if [ "$ITER" -ge "$MAX" ]; then
echo "ralph-ooo: max_iterations ($MAX) reached. Loop stopping." >&2
exit 0
fi
# Loop still running — inject continuation context
echo "RALPH_OOO_CONTINUE: Iteration $ITER/$MAX still running. Continue the ooo ralph loop. The boulder never stops." >&2
exit 1
'
if [ -f "$HOOK_SCRIPT" ]; then
echo -e "${YELLOW}⚠ ${HOOK_SCRIPT} already exists — overwriting${NC}"
fi
if [ "$DRY_RUN" = true ]; then
echo -e "${YELLOW}[DRY RUN] Would create ${HOOK_SCRIPT}${NC}"
else
printf '%s\n' "$HOOK_CONTENT" > "$HOOK_SCRIPT"
chmod +x "$HOOK_SCRIPT"
echo -e "${GREEN}✓ Created ${HOOK_SCRIPT}${NC}"
fi
# ── Step 2: Patch settings.json ───────────────────────────────────────────────
echo ""
echo -e "${BLUE}Step 2: Patch ~/.gemini/settings.json${NC}"
if [ "$DRY_RUN" = true ]; then
echo -e "${YELLOW}[DRY RUN] Would patch ${GEMINI_SETTINGS} with AfterAgent hook${NC}"
elif command -v python3 &>/dev/null; then
python3 - "$GEMINI_SETTINGS" "$HOOK_SCRIPT" "$GEMINI_EXT" <<'PYEOF'
import json, sys, os
settings_path = sys.argv[1]
hook_script = sys.argv[2]
ext_dir = sys.argv[3]
# Load or create settings
if os.path.exists(settings_path):
with open(settings_path) as f:
try:
settings = json.load(f)
except json.JSONDecodeError:
settings = {}
else:
settings = {}
# hooksConfig
settings.setdefault("hooksConfig", {})["enabled"] = True
# context includeDirectories
ctx = settings.setdefault("context", {})
dirs = ctx.setdefault("includeDirectories", [])
if ext_dir not in dirs:
dirs.append(ext_dir)
# AfterAgent hook entry
hook_entry = {
"matcher": "*",
"hooks": [{
"type": "command",
"command": f"bash {hook_script}",
"timeout": 10
}]
}
hooks = settings.setdefault("hooks", {})
after_agent = hooks.setdefault("AfterAgent", [])
# Check if already present
already = any(
any(h.get("command", "").endswith("ralph-ooo-check.sh")
for h in entry.get("hooks", []))
for entry in after_agent
)
if not already:
after_agent.append(hook_entry)
print("Added AfterAgent hook entry.")
else:
print("AfterAgent hook already present.")
with open(settings_path, "w") as f:
json.dump(settings, f, indent=2)
f.write("\n")
print(f"Updated {settings_path}")
PYEOF
echo -e "${GREEN}✓ Patched ${GEMINI_SETTINGS}${NC}"
else
echo -e "${YELLOW}⚠ python3 not found — skipping settings.json patch${NC}"
echo -e "${GRAY} Add manually to ${GEMINI_SETTINGS}:${NC}"
echo -e "${GRAY} {\"hooks\": {\"AfterAgent\": [{\"matcher\": \"*\", \"hooks\": [{\"type\": \"command\", \"command\": \"bash ${HOOK_SCRIPT}\", \"timeout\": 10}]}]}}${NC}"
fi
# ── Step 3: Extensions context directory ─────────────────────────────────────
echo ""
echo -e "${BLUE}Step 3: Extensions context directory (${GEMINI_EXT})${NC}"
EXT_CONTEXT="$GEMINI_EXT/CONTEXT.md"
EXT_CONTENT='# ralph-ooo — Ouroboros for Gemini CLI
Ouroboros specification-first workflow is active.
## ooo Commands
| Command | What It Does |
|---------|--------------|
| `ooo interview "topic"` | Socratic questioning until Ambiguity≤0.2 |
| `ooo seed` | Crystallize into immutable YAML spec |
| `ooo run [seed.yaml]` | Execute via Double Diamond |
| `ooo evaluate <id>` | 3-stage: Mechanical→Semantic→Consensus |
| `ooo evolve "topic"` | Evolutionary loop until Similarity≥0.95 |
| `ooo unstuck [persona]` | Lateral thinking |
| `ooo status [id]` | Drift check |
| `ooo ralph "task"` | Persistent loop — the boulder never stops |
## Ralph Loop State
State file: `.omc/state/ralph-ooo-state.json`
Completion signal: `<promise>DONE</promise>`
## Cancellation
`/ouroboros:cancel` — save checkpoint and exit
`/ouroboros:cancel --force` — clear all state
`ooo ralph continue` — resume from checkpoint
Source: https://github.com/Q00/ouroboros — MIT License
'
if [ "$DRY_RUN" = true ]; then
echo -e "${YELLOW}[DRY RUN] Would create ${EXT_CONTEXT}${NC}"
else
printf '%s\n' "$EXT_CONTENT" > "$EXT_CONTEXT"
echo -e "${GREEN}✓ Created ${EXT_CONTEXT}${NC}"
fi
# ── Summary ───────────────────────────────────────────────────────────────────
echo ""
echo -e "${GREEN}ralph-ooo × Gemini CLI setup complete.${NC}"
echo ""
echo -e "${BLUE}Next steps:${NC}"
echo -e " 1. Restart Gemini session"
echo -e " 2. Run with sandbox + YOLO mode: ${GREEN}gemini -s -y${NC}"
echo -e " 3. Start specification: ${GREEN}ooo interview \"your idea\"${NC}"
echo -e " 4. Start persistent loop: ${GREEN}ooo ralph \"your task\"${NC}"
echo ""
echo -e "${YELLOW}⚠ Known issue: Gemini v0.30.0 — stop_hook_active always false.${NC}"
echo -e "${GRAY} Workaround: hook reads .omc/state/ralph-ooo-state.json directly.${NC}"
echo ""
N:ralph
D:Ouroboros specification-first AI development — complete system. Socratic interview (Ambiguity≤0.2) → immutable YAML seed → Double Diamond execute → 3-stage evaluate → evolutionary evolve (Similarity≥0.95). Nine Minds agents on-demand. Ralph persistent loop with state persistence. The boulder never stops.
G:ralph ouroboros specification-first socratic interview seed evaluate evolve loop completion nine-minds double-diamond convergence drift boulder ooo multi-platform
U[7]:
1:Before writing any code — expose hidden assumptions via Socratic interview (Ambiguity≤0.2 required gate)
2:Vague requirements — crystallize into immutable YAML seed spec before any implementation
3:Long-running tasks requiring autonomous iteration until verification passes
4:Guaranteed completion — Ralph loop persists across session boundaries with state checkpointing
5:When stuck after repeated failures — Nine Minds lateral thinking personas break stagnation
6:Drift detection — measure how far execution deviates from original seed specification
7:Ontological convergence — evolutionary loop until consecutive generations ≥0.95 similar
S[10]{n,action,details}:
1:interview,Socratic interview,ooo interview "topic" → ask questions until Ambiguity≤0.2; Greenfield: Goal×40%+Constraint×30%+Success×30%; Brownfield adds Context×15%
2:seed,Crystallize spec,ooo seed → generate immutable YAML with goal/constraints/acceptance_criteria/ontology_schema; blocks at Ambiguity>0.2
3:run,Execute Double Diamond,ooo run [seed.yaml] → Discover→Define→Design→Deliver pipeline; uses seed from context if no path given
4:evaluate,3-stage verification,ooo evaluate <id> → Mechanical(free)→Semantic(standard)→Consensus(frontier); drift 0.0-0.15 excellent / 0.15-0.30 monitor / 0.30+ correct
5:evolve,Evolutionary loop,ooo evolve "topic" → Wonder→Reflect→Seed(Oₙ)→Execute→Evaluate until Similarity≥0.95 or 30 gens; --no-execute for ontology-only fast mode
6:ralph,Persistent loop,ooo ralph "task" → Execute(parallel)→Verify→Loop; saves .omc/state/ralph-ooo-state.json; resumes after interruption
7:unstuck,Lateral thinking,ooo unstuck [simplifier|hacker|contrarian|researcher|architect]; auto-select if no persona given
8:status,Drift check,ooo status [id] → measure Goal(50%)+Constraint(30%)+Ontology(20%) drift; warn at >0.3
9:setup,One-time setup,ooo setup → register MCP server globally; required for run/evaluate/evolve/status
10:cancel,Stop loop,/ouroboros:cancel (save checkpoint) or /ouroboros:cancel --force (clear all state); /ralph-ooo:cancel also works
R[9]:
1:Ambiguity≤0.2 is a hard gate — interview until the math says ready, not when you feel ready
2:The seed is immutable — never modify it after generation; all drift is measured against the original
3:Ontology convergence: Similarity=0.5×name_overlap+0.3×type_match+0.2×exact_match; threshold ≥0.95
4:Ralph state survives session resets in .omc/state/ralph-ooo-state.json — resume with "ooo ralph continue"
5:Each failure is data — verification_history drives next iteration strategy; do not give up under max_iterations
6:Completion promise syntax: <promise>DONE</promise> — default promise DONE; default max_iterations 10
7:4 stagnation signals: Similarity≥0.95 for 3 gens | Gen N≈Gen N-2 oscillation | 70% question overlap | hard cap 30 gens
8:Nine Minds loaded on-demand only — do not preload; match mind to situation (repeated failures→contrarian; no info→researcher; paralysis→hacker; structural→architect; too complex→simplifier)
9:Drift formula: Goal(50%)+Constraint(30%)+Ontology(20%); above 0.30 requires course correction before continuing
E[4]{desc,in,out}:
1:{Full ouroboros workflow from idea to verified delivery,ooo interview "build a REST API for todos" → ambiguity scored → ooo seed → YAML spec generated → ooo run → Double Diamond executes → ooo evaluate <id>,Socratic questions reduce Ambiguity from 0.82→0.16; seed YAML generated with 4 acceptance criteria; all 4 phases complete; 3-stage evaluation PASSED score 0.94}
2:{Ralph persistent loop until all tests pass,ooo ralph "fix all failing tests in the auth module" --max-iterations=10,Iteration 1 FAILED(0.65) 3 tests failing → Iteration 2 FAILED(0.85) 1 test failing → Iteration 3 PASSED(1.0); Ralph-OOO COMPLETE in 9m12s; state checkpointed at each step}
3:{Evolutionary ontology convergence,ooo evolve "design a notification system",Gen1 {Notification Event Channel} sim=N/A → Gen2 {Notification Event Channel Recipient Priority} sim=0.72 CONTINUE → Gen3 same sim=1.00 CONVERGED; ontology stabilized; Ralph stops}
4:{Breaking stagnation with unstuck personas,ooo unstuck contrarian (after 3 identical failures on DB schema),Contrarian challenges: "What if we don't need a relational schema at all?" → Reveals root assumption; new approach: event-sourced log → unblocked}
Related skills
FAQ
What ambiguity threshold gates the spec?
Socratic interviewing continues until Ambiguity <= 0.2 before a seed spec is generated.
Which platforms are supported?
Claude Code (full), Codex CLI (adapted), Gemini CLI (native), and OpenCode (native).