# Testing Tui Runtime > Cómo manejar el TUI de ralph-tui (`run`, modo watch, rutas de pausa/salida) de extremo a extremo en una terminal real, con un agente falso y un tracker beads de prueba, sin credenciales de IA. Fuente: https://skillsagentes.com/skills/subsy/ralph-tui/testing-tui-runtime Markdown: https://skillsagentes.com/skills/subsy/ralph-tui/testing-tui-runtime.md Repositorio: https://github.com/subsy/ralph-tui Autor: subsy Licencia: MIT Actualizado: hace 3 días Coste de contexto: 42 tok instalada, 2.6k tok al activarse, 2.6k tok con todos los archivos del bundle Bundle: 1 archivo, 10 KB Permisos que pide: ninguno declarado ## Instalación Un skill son archivos markdown: los mismos archivos valen para cualquier agente y lo único que cambia es el directorio de destino, es decir la bandera `--agent`. Añade `-g` para instalarlo en todos los proyectos de la máquina. ```bash # Claude Code npx -y skills add subsy/ralph-tui --skill testing-tui-runtime --agent claude-code # Cursor npx -y skills add subsy/ralph-tui --skill testing-tui-runtime --agent cursor # Codex npx -y skills add subsy/ralph-tui --skill testing-tui-runtime --agent codex # Gemini CLI npx -y skills add subsy/ralph-tui --skill testing-tui-runtime --agent gemini # Windsurf npx -y skills add subsy/ralph-tui --skill testing-tui-runtime --agent windsurf # Cline npx -y skills add subsy/ralph-tui --skill testing-tui-runtime --agent cline ``` ## Qué hace - Explica cómo probar el TUI de ralph-tui de extremo a extremo en una terminal real, usando `run`, watch mode y las rutas de pausa/salida - Configura agentes falsos (`echo.ts`, `slowecho.ts`) en `~/.config/ralph-tui/plugins/agents/` para simular ejecuciones sin credenciales de IA - Crea un tracker beads temporal (`bd`) por ejecución, aislado del `.beads` del propio repo - Documenta trampas conocidas: manejo de Ctrl+C, señales tempranas, locks obsoletos, sesiones recuperadas y fallos de `run --resume` - Añade un wrapper `runwatch.sh` para hacer visible en pantalla la latencia de arranque y salida ## Cuándo usarla - Un cambio debe probarse en el TUI real (watch mode, etiquetas de estado del motor, pausa/reanudación, cierre/salida) en vez de con pruebas unitarias ## Qué la activa - "Prueba el modo watch del TUI de ralph-tui con un agente falso" - "Verifica que Ctrl+C muestre el diálogo de interrupción en ralph-tui" - "Reproduce el bug del lock obsoleto en ralph-tui sin usar mi repo real" ## Antes de instalar - Requiere compilar el proyecto con `bun run build` y tener el binario `bd` instalado; no necesita credenciales de IA. - Necesita en el PATH: bun - Variables de entorno: RALPH_TEST_DIR - reads environment config ## Archivos - SKILL.md — 10 KB ## SKILL.md Reproducido tal cual desde subsy/ralph-tui bajo MIT. Esta sección es el documento original y está en inglés. # Runtime/E2E testing of the ralph-tui TUI Use this when a change must be proven in the real TUI (watch mode, engine status labels, pause/resume, shutdown/quit paths) rather than with unit tests. ## Build & run ```bash cd /path/to/ralph-tui && bun run build # produces dist/cli.js ``` Run the built CLI (not `bun run dev`) so behaviour matches shipped code: ```bash bun /path/to/ralph-tui/dist/cli.js run [flags] ``` ## Scratch tracker (never touch the repo's own .beads) Create a throwaway project dir with its own beads store and drive scenarios with `bd`: ```bash export RALPH_TEST_DIR="$(mktemp -d "${TMPDIR:-/tmp}/ralph-tui-run.XXXXXX")" && cd "$RALPH_TEST_DIR" bd init # or `bd create ...` which bootstraps the store bd create "Watch mode epic" --type epic -p 1 # note the epic id bd prints bd create "Alpha task" --type task -p 2 --parent ``` A **fresh** dir per run, not a fixed one: a reused dir carries over `.beads` tasks, the `.ralph-tui` session file, locks and guards — exactly the things most scenarios here assert on, so a `Recovered stale session` banner or a stale-lock prompt from the *previous* run reads as a finding of the build under test. The unique dir also gives the run a unique epic id, which is how you address its process (see the signal trap below). Gotchas: - `bd` commands must be run **with the scratch dir as the working directory**, otherwise you get "no beads database found". - With `--tracker beads`, the TUI **requires `--epic `**; without it the TUI shows "No epics found" and interactive epic selection blocks automation. - `br` (beads-rust) may not be installed even though AGENTS.md references it; `bd` works. ## Fake agents (no AI credentials needed) Put plugins in `~/.config/ralph-tui/plugins/agents/`: - `echo.ts` — returns `echo-agent: local fake response\nCOMPLETE` instantly. - `slowecho.ts` — same but sleeps ~25s in interruptible 500 ms chunks. Essential for testing quit/pause **mid-iteration**; an instant agent gives you no window to interrupt. Select with `--agent echo` / `--agent slowecho`. ## Making timing visible on screen Wrap the CLI so quit latency is provable in the recording: ```bash #!/bin/bash cd "${RALPH_TEST_DIR:?export RALPH_TEST_DIR to the scratch dir first}" export PATH="$PATH:$HOME/.local/bin" echo "START $(date +%H:%M:%S.%3N) args: $*" bun /path/to/ralph-tui/dist/cli.js run "$@" echo "=== PROCESS EXITED code=$? at $(date +%H:%M:%S.%3N) ===" exec bash ``` Typical invocation: `./runwatch.sh --watch --poll 60 --agent echo --tracker beads --epic --no-setup --force` Use a long `--poll` (60s) to make a stalled pause/quit obvious, and a short one (10s) when you want auto-pickup to happen quickly. ## TUI keys `s` start · `p` pause/resume · `q` → quit dialog → `y` · `d` dashboard · `r` refresh. Header status labels: `Waiting` (watch idle), `Selecting`, `Executing`, `Paused`, `Complete`. Dashboard shows `Waiting for new tasks` when watch-idle. ## Known traps - **Interrupt (Ctrl+C) path**: on builds that include the #431 fix (`src/tui/utils/keyboard-shortcuts.ts` + `onInterruptRequest` in `RunApp.tsx` + `exitSignals: ['SIGQUIT','SIGABRT']` in `run.tsx`), keyboard Ctrl+C and external `kill -INT ` both render the `⚠ Interrupt Ralph?` dialog with the display intact; `n`/`Esc` cancel, `y` exits code 0 in ~2s and resets the active task to `open`, and a second Ctrl+C within ~1s force-quits via `process.exit(1)` (wrapper `code=1`, terminal left un-repainted; on builds whose `exit` handler calls `releaseLockSync` the force quit no longer leaves a lock file behind, on older ones it does). On older builds Ctrl+C is a complete no-op and `kill -INT` blanks the display and hangs, so always confirm which build you are on before blaming a change. - **Ctrl+Shift+C is indistinguishable from Ctrl+C in most terminals**: konsole sends byte `0x03` for both (verify with `stty -isig; cat -v` — Ctrl+Shift+C prints `^C`, Alt+C prints `^[c`), so the "copy" shortcut opens the interrupt dialog whenever the terminal does not consume it itself (konsole only consumes it when a konsole-level text selection exists). Alt+C is safely distinct. Clipboard *contents* cannot be verified on a box without `xclip`/`xsel`/`wl-paste` (that is what `src/utils/clipboard.ts` shells out to on Linux) — record the clipboard write as untested. - **Early-startup signals need timing, and are quirky**: the app's SIGINT/SIGTERM handlers are not installed for roughly the first ~0.7s. Drive it with `( sleep 0.5; kill -INT "$(pgrep -f "cli\.js run.*--epic $EPIC_ID")" ) & ./runwatch.sh ...`, where `$EPIC_ID` is this run's epic — check the pattern matches exactly one pid (`pgrep -cf ...`) before signalling, and note the wrapper script is a *different* process from the CLI it launches, so signal the pid you matched rather than the wrapper. Do not use `pkill -f 'dist/cli.js run'`: it hits every ralph run on the box, including a parallel test or a `main` worktree build you are comparing against, and mutates their session and task state. Historic behaviour (before the #434 fix in `src/session/lock.ts`): SIGINT in that window exited `130` but left a stale lock, and SIGTERM was *delivered but ignored* (the TUI mounted and kept running). On builds where `registerLockCleanupHandlers` owns the startup signals (guarded by `process.listenerCount(signal) > 1`), expect `code=143` for SIGTERM / `code=130` for SIGINT at every delay in the window, with `.ralph-tui/ralph.lock` removed; a signal landing *before* `acquireLockWithPrompt` (~0.05s) uses default disposition but cannot leave a lock. Always sweep several delays (0.05/0.2/0.3/0.4/0.5/0.7s), log that the signal was actually sent, and check `ls .ralph-tui/ralph.lock` plus the next launch's banner each time. Two signals in quick succession inside the window should still yield a single clean 130/143, never `code=1`. - **`Recovered stale session` is not the same thing as `Stale lock detected`**: the lock file can be correctly removed while `.ralph-tui/session.json` keeps `status: "running"`, in which case *every* next launch prints `⚠ Recovered stale session / Session status set to "interrupted" (resumable)` — even after a graceful `q`/`y` exit (`code=0`). Check `jq .status .ralph-tui/session.json` and `session-meta.json` before attributing that banner to a lock/signal change; it may be an independent session-persistence bug. - **In TUI mode the process does not exit by itself** when all tasks are done in non-watch mode; it parks on `Complete` until you quit. To prove "exits when work runs out", use headless mode: `--no-tui` (alias `--headless`) exits with code 0 and prints a run summary. Headless watch mode logs `[watch] All tasks complete — polling every Ns` and stays alive. - **Killed sessions may leave a stale lock** (older builds; fixed once the lock layer owns startup signals and the `exit` handler releases synchronously): the next launch prompts "Remove the stale lock and continue? (Y/n)" *before* the TUI starts. Answer `y` first; keys you send too early (e.g. `s`) land in that prompt. Prefer graceful `q`/`y` exits to avoid this. - After creating a task externally, allow up to one full poll interval plus a few seconds before concluding auto-pickup failed. - **Lock guard file (`.ralph-tui/ralph.lock.guard`) and `lockId`**: on builds that serialize lock mutations, `.ralph-tui/ralph.lock` carries a `lockId` nonce and every create/stale-clean/ `--force`/release goes through a guard file created with `O_EXCL`. Useful observer helper: print the lock's `pid`/`lockId`, whether the guard exists (and its contents), and `pgrep`ed ralph pids, and sample it before/after every scenario. The guard should never be observed present while a run merely executes — only during a mutation. Things worth planting by hand: an empty or `not-json` guard (should be reclaimed as malformed after ~250ms and the run starts normally), a guard naming a *dead* pid (reclaimed), and a guard naming a *live* pid (respected: acquire fails after ~2s with `Timed out waiting for the session lock (another ralph-tui process may be starting or exiting)`). On such builds a guard held past the sync budget at exit time is expected to leave the lock behind (later recovered as stale) rather than unlink it — a lock left behind there is a pass; a hang, a multi-second stall, or a *live* process's lock disappearing is the bug. Make sure the "live pid" in a planted guard is really alive (`kill -0`); a pid that has already exited silently converts the test into the dead-pid case. - **`run --resume` may fail where standalone `resume` works**: `run.tsx` acquires the session lock before calling `resumeSession`, which acquires again and refuses because a lock exists — observed as `Resuming previous session... / Failed to resume session` with exit 1, while `ralph-tui resume` on the same interrupted session starts fine. Reproduced on `main` too, so treat it as pre-existing unless the build under test claims to fix it; always cross-check against a `git worktree` build of `main` before calling it a regression. - **Watch for an orphaned run with no lock file**: observed once — the TUI painted nothing at all yet the engine kept executing iterations and `.ralph-tui/ralph.lock` was absent. That is the signature of an uncaught exception handler that releases the lock without exiting. It did not reproduce in follow-up attempts; if you hit a blank TUI, capture stdout/stderr by wrapping the run in `script -q -c "./runwatch.sh ..." /tmp/run.log` (this preserves the TTY, unlike a pipe) before killing it. Note `runwatch.sh` ends with `exec bash`, so a `script`-wrapped run leaves you in an inner shell — type `exit` to continue a scripted loop. ## Devin Secrets Needed None — the fake agent plugins and the local `bd` store avoid all external credentials. ## Dónde encaja - Categoría: [Testing y QA](https://skillsagentes.com/categorias/testing-qa.md) — Flujos de testing unitario, de integración y end-to-end. - Creador: [subsy](https://skillsagentes.com/creators/subsy.md) — 0 skills en el directorio - [Todas las skills](https://skillsagentes.com/skills.md) - [Ranking de instalaciones](https://skillsagentes.com/ranking.md) ## Otras skills del mismo repositorio - [Ralph Tui Prd](https://skillsagentes.com/skills/subsy/ralph-tui/ralph-tui-prd.md): Genera un Product Requirements Document (PRD) para orquestación de tareas con ralph-tui, con historias de usuario convertibles a issues de beads o prd.json. - [Ralph Tui Create Beads](https://skillsagentes.com/skills/subsy/ralph-tui/ralph-tui-create-beads.md): Convierte PRDs en beads para la ejecución con ralph-tui. Crea un epic con beads hijas por cada historia de usuario cuando quieres usar ralph-tui con beads como fuente de tareas. - [Ralph Tui Create Json](https://skillsagentes.com/skills/subsy/ralph-tui/ralph-tui-create-json.md): Convierte PRDs al formato prd.json para la ejecución de ralph-tui. Crea archivos JSON de tareas con user stories, criterios de aceptación y dependencias. - [Ralph Tui Create Beads Rust](https://skillsagentes.com/skills/subsy/ralph-tui/ralph-tui-create-beads-rust.md): Convierte PRDs en beads para la ejecución de ralph-tui usando beads-rust (CLI `br`). Crea un epic con beads hijos para cada historia de usuario. ## Skills relacionadas - [Pr Status Triage](https://skillsagentes.com/skills/vercel/next.js/pr-status-triage.md): Tría fallos de CI y comentarios de revisión de PR con scripts/pr-status.js: prioriza por bloqueo (build, lint, tipos, tests), empareja variables de CI para reproducir en local y distingue flakies. - [Sandbox Bench](https://skillsagentes.com/skills/vercel/next.js/sandbox-bench.md): Compara el rendimiento de cambios de React o Next.js en VMs de Vercel Sandbox con estadística A/B pareada: rps, latencia, p95, TTFB, RSS y bytes de documento y Flight. - [Ios Qa](https://skillsagentes.com/skills/garrytan/gstack/ios-qa.md): QA en dispositivo iOS real para apps SwiftUI, con bucle de agente guiado por visión sobre USB (gstack). - [Health](https://skillsagentes.com/skills/garrytan/gstack/health.md): Panel de calidad de código: envuelve los checkers y linters del proyecto, calcula una puntuación compuesta 0-10 y sigue la evolución en el tiempo. (gstack) - [Qa](https://skillsagentes.com/skills/browser-use/browser-use/qa.md): Hace QA de un sitio o app web y devuelve una puntuación de 1 a 5 (5 = perfecto, 1 = roto) con evidencia, usando un navegador real en la nube de Browser Use, incluso con localhost. --- Skills Agentes · [Índice de páginas en markdown](https://skillsagentes.com/sitemap.md) · [Inicio](https://skillsagentes.com/index.md)