RALPH Console Wrapper (SS-07)
rocky intermediate 6 min read
ELI5
The console is the customer counter; RALPH is the kitchen. The customer never walks into the kitchen — they hand the console an order (prompts.yaml + RunConfig), the console signs it with the kitchen’s shared token, and the kitchen streams back live updates while it cooks. Cancelling mid-cook needs a manager (admin) on duty.
Technical Deep Dive
Three console-side seams
submitRun(workspace_slug: string, prompts_yaml: string, config: RunConfig): Promise<{ run_id: string }>streamEvents(run_id: string): AsyncIterable<JournalEvent>cancelRun(run_id: string): Promise<void> // admin-only| Seam | Console route | RBAC |
|---|---|---|
submitRun | POST /api/ralph/runs | operator + admin |
streamEvents | GET /api/ralph/runs/[id] (SSE) | observer + operator + admin |
cancelRun | POST /api/ralph/runs/[id]/cancel | admin only |
Worker shape (ralph serve)
The standalone rocky run CLI keeps working unchanged; ralph serve is additive:
- HTTP server (FastAPI) accepts
RunConfig + prompts.yaml. - Background worker (RQ or arq) executes the existing
plan → judge → execute → audit → mergepipeline. - Streams
run.jsonlevents as SSE. - Auth is a static HMAC bearer pulled from SS-06 VAULT (
secrets/ralph/serve_token), never exposed to the browser; the console route is the only thing that talks to the worker.
End-to-end flow
sequenceDiagram autonumber participant Browser participant Console as console route participant VAULT as SS-06 VAULT participant Worker as ralph serve (FastAPI) participant Pipe as RALPH pipeline participant RELAY as SS-05 RELAY → HATCH participant Store as SS-04 object store
Browser->>Console: POST /api/ralph/runs (prompts.yaml + RunConfig) Console->>VAULT: read secrets/ralph/serve_token VAULT-->>Console: HMAC bearer Console->>Worker: POST /runs (Authorization: Bearer ...) Worker-->>Console: { run_id } Console->>RELAY: ralph.run.started Console-->>Browser: { run_id }
Browser->>Console: GET /api/ralph/runs/{id} (SSE) Console->>Worker: GET /runs/{id}/events (SSE proxy) loop per pipeline step Pipe->>Worker: emit transition (KAHN shape) Worker-->>Console: SSE frame Console-->>Browser: SSE frame (validated) Worker->>RELAY: deviation/major event end Pipe->>Store: plan.md, deviation_pre/post.md, diff.patch, transcripts Pipe->>Worker: run end Worker-->>Console: SSE final frame Console->>RELAY: ralph.run.endedTransport knob
RALPH_TRANSPORT={in-process|sidecar|remote} selects worker location. The console’s RalphClient is the single seam — swapping transports never changes call sites. Phase 3e adds an analogous RALPH_CRDT_TRANSPORT for the prompt editor (see rocky-007).
Failure handling
| Class | Where surfaced | Behaviour |
|---|---|---|
worker_unreachable | console can’t reach worker | ”worker offline” banner, queue submission 60s, then fail |
pipeline_deviation | RALPH judge marks major | existing on-failure policy (stop / skip / realign) — unchanged |
flowchart LR sub[submitRun] -->|HMAC ok| accept[run_id] sub -->|worker offline| q[queue 60s] q -->|recovered| accept q -->|timeout| fail[surface error] accept --> stream[streamEvents SSE] stream -->|admin| cancel[cancelRun] stream -->|run end| store[artifacts → SS-04]Key Terms
ralph serve→ additive HTTP/worker mode; CLI mode (rocky run) keeps working- HMAC bearer → static token in SS-06 VAULT shared between console and worker; never sent to browser
- JournalEvent → KAHN-shaped transition the worker streams over SSE (rocky-006)
- Deviation → judge classification of plan vs. actual; major deviations route to HATCH via RELAY in addition to per-action HATCH events
Q&A
Q: Why is the bearer never embedded in the client bundle? A: The bearer authorises the worker, not the user. Embedding it would let any browser talk to the worker bypassing Airlock and HATCH. The console proxies every worker call so the three-step tenancy invariant runs first.
Q: Who can cancel a run mid-flight?
A: Admin only. cancelRun is wired to the admin role in the SS-07 role table; observers and operators see runs but cannot abort them.
Q: Where do artifacts (plan.md, diff.patch, transcripts) land?
A: SS-04 WORKSPACE’s existing object store. RALPH writes; the dashboard panel ralph.runs and the per-run page /ralph/runs/[id] link to them.
Examples
A drive-through: the cashier window (console) takes your order and handshakes the kitchen with a stamped slip (HMAC). The pickup window (SSE) shows what stage your meal is at. Only the manager (admin) can yell “cancel that order”; once it is plated (artifacts to SS-04), the receipt prints whether or not anyone is still watching the screen.
neighbors on the map
- Ralph Convergence Loop tuning max_ralph_iters for a flaky node
- Prompt-DAG Scheduler designing a graph.json for a new repo
- End-to-End Chain Execution Request Flow tracing a chain execution through the entire system
- WebSocket Session Lifecycle adding a new privileged WS handler