Files
neuron-tai/.scratch/distributed-inference-network/issues/15-ralph-agent-agnostic-status-aware.md
Dobromir Popov d3bb50a894 feat(prd): add US-015 — Ralph agent-agnostic runner + status-field dashboard
Status-field awareness:
- Replace passes:bool with status field in ralph_progress.py
- Six buckets: done, attention, active, in-design, ready, blocked
- Dashboard shows ⚠ Attention Required section for to-revise/needs-review
- auto skips attention stories by default; --include-revise overrides

Agent agnosticism:
- --agent codex|claude|openrouter|custom on all run commands
- Persistent config in .ralph-tui/agent-config.json via set-agent subcommand
- OpenRouter adapter: calls API directly when ralph-tui lacks native plugin
- custom: --agent-cmd <script> receives prompt file as $1

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 16:10:28 +03:00

6.1 KiB

US-015 — Ralph: agent-agnostic runner + status-field-aware dashboard

Two tightly coupled improvements to the Ralph workflow tooling:

  1. Status-field awarenessralph_progress.py currently reads passes: true/false everywhere. Replace all passes references with the rich status field introduced in the prd.json schema migration. Surface to-revise and needs-review stories as an attention list rather than treating them like failed or blocked tasks.

  2. Agent-agnostic runner — Ralph currently hardcodes agentPlugin: "codex" and always calls ralph-tui run --agent codex. Make the agent selectable per session with first-class support for Claude Code CLI, OpenRouter (unified API covering GPT-4, Mistral, DeepSeek, Llama, etc.), and the existing Codex plugin.

Part 1: Status-field awareness in ralph_progress.py

What to replace

Every occurrence of story.get("passes") in scripts/ralph_progress.py must be replaced with a helper that reads the status field with a passes fallback for backward compatibility:

# Status → done mapping (backward-compat: passes=True counts as done if no status field)
_DONE_STATUSES = {"done"}
_ATTENTION_STATUSES = {"to-revise", "needs-review"}
_ACTIVE_STATUSES = {"in-progress"}
_DESIGN_STATUSES = {"in-design"}

def _is_done(story: dict) -> bool:
    status = story.get("status")
    if status:
        return status in _DONE_STATUSES
    return bool(story.get("passes"))  # fallback

def _needs_attention(story: dict) -> bool:
    return story.get("status") in _ATTENTION_STATUSES

def _is_active(story: dict) -> bool:
    return story.get("status") in _ACTIVE_STATUSES

def _is_in_design(story: dict) -> bool:
    return story.get("status") in _DESIGN_STATUSES

_story_sets rewrite

Current behaviour lumps to-revise into the "done" bucket (because passes=True) or the "open" bucket. New behaviour:

done         → status == "done"  (or passes=True fallback)
attention    → status in {to-revise, needs-review}   ← new bucket
active       → status == "in-progress"
in-design    → status == "in-design"               (treated as blocked — needs human before agent)
ready        → status == "open" AND all deps done
blocked      → status == "open" AND some dep not done

_deps_done rewrite

Dependency is satisfied when the dep story _is_done() — not when passes=True.

Dashboard additions

Ralph progress: Distributed Inference Network
PRD: .scratch/distributed-inference-network/prd.json
[############################] 13/15 complete (86%)
Done: 13   Ready: 1   Attention: 2   Blocked: 0

⚠ Attention required (review before running):
  ⚠ US-002  02 — Two-node shard pipeline
             Wire format replaced by US-011 binary protocol; verify tests.
  ⚠ US-005  05 — OpenAI-compatible gateway
             Gateway orchestration superseded by US-014; defer until US-014 lands.

→ US-014  14 — Tracker-as-first-layer-node (inference entry point)

auto command behaviour

auto skips to-revise and needs-review stories — they need human review before an agent re-runs them. Add --include-revise flag to override this for unattended runs.

_review_report additions

Include a dedicated Attention Required section in the generated review brief listing all to-revise and needs-review stories with their status_reason.


Part 2: Agent-agnostic runner

Agent selection

Add --agent option with these values:

Value CLI invoked Config required
codex ralph-tui run --agent codex ... OPENAI_API_KEY (existing)
claude ralph-tui run --agent claude ... ANTHROPIC_API_KEY
openrouter ralph-tui run --agent openrouter ... OPENROUTER_API_KEY + --model
custom --agent-cmd <path> user-defined

If ralph-tui does not natively support a requested agent plugin, ralph_progress.py falls back to invoking the agent CLI directly with the task prompt file, bypassing ralph-tui run entirely.

Persistent agent config

Save the last-used agent choice to .ralph-tui/agent-config.json so it doesn't have to be passed on every command:

{
  "agent": "openrouter",
  "model": "anthropic/claude-opus-4",
  "updatedAt": "2026-06-29T..."
}

--agent on the CLI always overrides the saved config. ralph_progress.py set-agent --agent openrouter --model openai/gpt-4o writes the config file.

OpenRouter adapter

When agent == "openrouter" and ralph-tui doesn't natively support it, ralph_progress.py implements a thin adapter:

  1. Read the task prompt from the issue file + prd.json story
  2. POST to https://openrouter.ai/api/v1/chat/completions with OPENROUTER_API_KEY
  3. Stream response to stdout
  4. Watch prd.json for status change to detect task completion
  5. Timeout after configurable duration (default: 10 minutes per task)

The OpenRouter model is set via --model (e.g. openai/gpt-4o, mistralai/mistral-large, meta-llama/llama-3-70b-instruct). Default: anthropic/claude-opus-4.

custom agent

--agent custom --agent-cmd ./my-agent.sh — Ralph passes the task prompt file path as $1. The script exits 0 on success. This makes Ralph compatible with any future agent tool without code changes.


Acceptance Criteria

  • All passes reads in ralph_progress.py replaced with _is_done() helper (with fallback)
  • _story_sets returns five buckets: done, attention, active, in-design, ready, blocked
  • Dashboard shows ⚠ Attention required section with status_reason for each affected story
  • auto skips to-revise / needs-review by default; --include-revise overrides
  • ralph_progress.py set-agent --agent <name> writes .ralph-tui/agent-config.json
  • --agent codex|claude|openrouter|custom accepted by all subcommands that invoke Ralph
  • ralph_progress.py run-next --agent openrouter --model openai/gpt-4o runs a task via OpenRouter adapter
  • ralph_progress.py run-next --agent custom --agent-cmd ./my-agent.sh runs a task via custom script
  • python -m pytest passes from repo root
  • Commit only this story's changes