This commit is contained in:
2026-05-30 19:37:17 -04:00
parent 81e0e8ec1c
commit e6a8c8bedc
19 changed files with 2393 additions and 858 deletions

View File

@@ -0,0 +1,38 @@
# 01. Fix `loadConfig` to return defaults gracefully when `.ralph/config.yaml` is missing
meta:
id: ralph-loop-fixes-01
feature: ralph-loop-fixes
priority: P1
depends_on: []
tags: [implementation, utils]
objective:
- `loadConfig()` should return `DEFAULT_CONFIG` silently when `.ralph/config.yaml` does not exist, without logging a warning to stderr
deliverables:
- Modified `src/utils.ts``loadConfig()` function
steps:
- Open `src/utils.ts` and locate `loadConfig()`
- Add `fs.existsSync()` check before `fs.readFileSync()`
- If config file does not exist, return a deep copy of `DEFAULT_CONFIG` without any console output
- If config file exists but is malformed, fall back to defaults silently
- Remove or suppress the `console.warn()` call
tests:
- Manual: Run `/ralph resume` in a project directory with no `.ralph/` directory — should not print warning
- Manual: Run `/ralph run` in a project with `.ralph/progress.json` but no `config.yaml` — should proceed with defaults
acceptance_criteria:
- No console warning when config.yaml is missing
- `loadConfig()` returns a valid `RalphConfig` object in all cases
- Existing behavior with valid config.yaml is unchanged
validation:
- Check `src/utils.ts` loadConfig function returns silently on missing file
- Verify no `console.warn` or `console.error` in the missing-config path
notes:
- Current code at line ~145 in utils.ts: `fs.readFileSync(configPath, "utf-8")` throws ENOENT
- The try-catch does catch it but still logs the warning — the warning is noisy for normal usage where config is optional

View File

@@ -0,0 +1,42 @@
# 02. Replace `spawnPi` with `--print` mode and stdin piping
meta:
id: ralph-loop-fixes-02
feature: ralph-loop-fixes
priority: P1
depends_on: []
tags: [implementation, utils]
objective:
- Replace `spawnPi()` so it invokes `pi --print` with prompt content piped via stdin, instead of using non-existent `--no-stream` and `--prompt` flags
deliverables:
- Modified `src/utils.ts``spawnPi()` function
- Updated `src/executor.ts` — import and call site for `spawnPi`
steps:
- Open `src/utils.ts` and locate `spawnPi()`
- Replace `spawnSync` args from `["--no-stream", "--prompt", promptFile, ...]` to `["--print"]`
- Read the prompt file content and pass it as `input` to `spawnSync`
- The `input` option accepts a string that is piped to the child process stdin
- Keep `encoding`, `timeout`, and `maxBuffer` options as-is
- Update the function signature if needed (no longer needs `promptFile` path, can take prompt content directly, or read it internally)
tests:
- Manual: Spawn pi with a simple prompt — verify it returns text output and exits cleanly
- Manual: Verify `result.stdout` contains the pi response text (not NDJSON or event stream)
acceptance_criteria:
- `spawnPi()` exits with code 0 on successful execution
- `result.stdout` contains plain text response from pi
- No "Unknown options: --no-stream, --prompt" error
validation:
- Run `pi --print` with piped input manually to verify behavior
- Check spawnSync call uses `["--print"]` args and `input` option
notes:
- Pi's `--print` flag runs in non-interactive mode: reads from stdin, writes to stdout, exits
- `spawnSync` accepts an `input` option (string) that pipes to child stdin
- Current broken args: `["--no-stream", "--prompt", promptFile]`
- The `extractTextFromEvent()` function can be simplified or removed since `--print` returns plain text

View File

@@ -0,0 +1,47 @@
# 03. Replace `sendMessage` with `ctx.ui` progress API
meta:
id: ralph-loop-fixes-03
feature: ralph-loop-fixes
priority: P1
depends_on: [ralph-loop-fixes-04]
tags: [implementation, executor]
objective:
- Replace all `piApi.sendMessage({ customType: "ralph-progress", display: true })` calls with `ctx.ui.notify()` and `ctx.ui.setStatus()` to avoid TUI crash from unregistered custom message renderer
deliverables:
- Modified `src/executor.ts` — remove `sendProgressMessage()`, replace with `ctx.ui` calls
- Modified `src/executor.ts` — remove `formatToolUsage()` if no longer needed, or keep for status text
steps:
- Open `src/executor.ts`
- Remove `sendProgressMessage()` function entirely
- In `runTask()`, replace `sendProgressMessage(piApi, task, project, "starting")` with `ctx.ui.setStatus("ralph", "Running ${task.id}: ${task.title}")`
- In `runTask()` success path, replace `sendProgressMessage(..., "completed")` with `ctx.ui.notify()` for completion summary
- In `runTask()` failure path, replace `sendProgressMessage(..., "failed")` with `ctx.ui.notify()` for error
- In `executeBatch()`, replace batch start `piApi.sendMessage()` with `ctx.ui.setStatus()`
- In `executeTask()`, replace retry `piApi.sendMessage()` with `ctx.ui.notify()`
- Remove `piApi: ExtensionAPI` parameter from all executor functions (replaced by `ctx: ExtensionCommandContext`)
- Remove unused `ExtensionAPI` import from executor.ts
tests:
- Manual: Run a task and verify progress appears in the Pi UI without crash
- Manual: Verify no `child.render is not a function` error
acceptance_criteria:
- No TUI crash during task execution
- Progress messages visible to user via `ctx.ui`
- `sendProgressMessage()` function removed from codebase
- `piApi.sendMessage()` no longer called anywhere in executor
validation:
- Grep for `sendMessage` in executor.ts — should only appear in comments or not at all
- Grep for `customType.*ralph-progress` — should be removed
- Verify `ctx.ui.notify` and `ctx.ui.setStatus` are used instead
notes:
- `ctx.ui.notify(message, type)` shows a notification — use "info" for progress, "error" for failures
- `ctx.ui.setStatus(key, text)` sets footer status text — good for "Running task X" updates
- `ctx.ui.setStatus(key, undefined)` clears the status
- The TUI crash (`child.render is not a function`) happens because `customType: "ralph-progress"` has no registered renderer via `pi.registerMessageRenderer()`

View File

@@ -0,0 +1,47 @@
# 04. Thread `ExtensionCommandContext` through `executeBatch`
meta:
id: ralph-loop-fixes-04
feature: ralph-loop-fixes
priority: P1
depends_on: []
tags: [implementation, plumbing]
objective:
- Pass `ctx: ExtensionCommandContext` from command handlers through to all executor functions that need it, replacing the missing `piApi: ExtensionAPI` parameter
deliverables:
- Modified `index.ts` — all `executeBatch()` calls pass `ctx` as 6th parameter
- Modified `src/executor.ts``executeBatch()`, `executeTask()`, `runTask()`, `executeBatchParallel()` accept `ctx: ExtensionCommandContext`
steps:
- Open `src/executor.ts`
- Add `import type { ExtensionCommandContext } from "@earendil-works/pi-coding-agent"`
- Update `executeBatch()` signature: add `ctx: ExtensionCommandContext` as 6th parameter (after `progress`)
- Update `executeTask()` signature: add `ctx: ExtensionCommandContext` parameter
- Update `runTask()` signature: add `ctx: ExtensionCommandContext` parameter
- Update `executeBatchParallel()` signature: add `ctx: ExtensionCommandContext` parameter
- Thread `ctx` through all internal calls (batch → task → run)
- Open `index.ts`
- In `handleRun()`: pass `ctx` to `executeBatch()`
- In `handleResume()`: pass `ctx` to `executeBatch()`
- In `handleNext()`: pass `ctx` to `executeBatch()`
tests:
- Manual: `/ralph run` should execute without "undefined is not a function" errors
- Manual: `/ralph resume` should execute without context-related errors
acceptance_criteria:
- `executeBatch()` receives a valid `ExtensionCommandContext` in all call paths
- No `undefined` access errors when executor calls `ctx.ui.*`
- TypeScript compiles without errors
validation:
- Run `npx tsc --noEmit` in extension directory
- Verify `ctx` parameter exists in all executor function signatures
- Verify all call sites in index.ts pass `ctx`
notes:
- `ExtensionCommandContext` extends `ExtensionContext` and adds session control methods
- Command handlers receive `ExtensionCommandContext`, not bare `ExtensionContext`
- The `piApi` parameter was `ExtensionAPI` which has `sendMessage()` — we're replacing it with `ctx` which has `ctx.ui` for UI access

View File

@@ -0,0 +1,39 @@
# 05. Fix sequential mode batch labels
meta:
id: ralph-loop-fixes-05
feature: ralph-loop-fixes
priority: P2
depends_on: [ralph-loop-fixes-04]
tags: [implementation, ui]
objective:
- Suppress "Batch N:" label for single-task batches; use numbered list format (1., 2., 3.) for sequential task execution to match original behavior
deliverables:
- Modified `src/executor.ts``executeBatch()` console output
steps:
- Open `src/executor.ts` and locate `executeBatch()`
- In the batch header log, check if `tasks.length === 1`
- If single task: log `[ralph] Running task ${task.id}: ${task.title}` (no "Batch N" wrapper)
- If multiple tasks: keep existing `=== Batch N (M tasks) ===` format
- Track global task counter for sequential numbered output if needed
tests:
- Manual: Run a single-task batch — verify no "Batch N" in output
- Manual: Run a multi-task batch — verify "Batch N" still appears
acceptance_criteria:
- Single-task batches do not show "Batch N:" prefix
- Multi-task batches still show batch header
- Output format matches original: `[ralph] Running task 001: Title`
validation:
- Check `console.log` output in executeBatch for conditional formatting
- Verify single-task path uses task-focused label
notes:
- Original behavior: single tasks show numbered list (1., 2., 3.), batches show "Batch N:"
- Current code always shows `[ralph] === Batch N (M tasks) ===` regardless of batch size
- This is cosmetic but matches user preference for compact UI

View File

@@ -0,0 +1,40 @@
# 06. Simplify `parseToolUsage` for plain text output
meta:
id: ralph-loop-fixes-06
feature: ralph-loop-fixes
priority: P2
depends_on: [ralph-loop-fixes-02]
tags: [implementation, utils]
objective:
- Remove NDJSON event parsing from `parseToolUsage()` since `pi --print` returns plain text, not structured event streams
deliverables:
- Modified `src/utils.ts``parseToolUsage()` function
steps:
- Open `src/utils.ts` and locate `parseToolUsage()`
- Remove the NDJSON parsing block (lines that check `line.startsWith("data: ")` and `JSON.parse`)
- Keep only the regex fallback that counts tool mentions in plain text output
- Remove `extractTextFromEvent()` if no longer needed (plain text from `--print` needs no extraction)
- Update `executor.ts` to call `parseToolUsage()` directly on `result.stdout` without `extractTextFromEvent()`
tests:
- Manual: Run a task that uses multiple tools — verify tool counts are captured from plain text output
- Manual: Verify no JSON parse errors in tool usage parsing
acceptance_criteria:
- `parseToolUsage()` works correctly on plain text output
- No JSON parsing logic remains in `parseToolUsage()`
- Tool counts ([read], [write], [edit], [bash]) are still extracted via regex
validation:
- Grep for `JSON.parse` in parseToolUsage — should be removed
- Grep for `data:` prefix check — should be removed
- Verify regex-based tool counting still present and functional
notes:
- `pi --print` returns plain text, not NDJSON event stream
- The regex fallback patterns (`\[read\]`, `read(`, etc.) are sufficient for counting tool mentions
- `extractTextFromEvent()` was only needed for NDJSON — can be removed or simplified to identity function

View File

@@ -0,0 +1,26 @@
# Ralph-Loop Extension Fixes
Objective: Fix critical bugs preventing `/ralph resume` from working — broken CLI flags, unthreaded context, missing config, and TUI crash.
Status legend: [ ] todo, [~] in-progress, [x] done
Tasks
- [x] 01 — Fix `loadConfig` to return defaults gracefully when `.ralph/config.yaml` is missing → `01-fix-loadconfig-graceful-default.md`
- [x] 02 — Replace `spawnPi` with `--print` mode and stdin piping → `02-fix-spawnpi-print-mode.md`
- [x] 03 — Replace `sendMessage` with `ctx.ui` progress API → `03-replace-sendmessage-with-ctx-ui.md`
- [x] 04 — Thread `ExtensionCommandContext` through `executeBatch``04-thread-ctx-through-execute-batch.md`
- [x] 05 — Fix sequential mode batch labels → `05-fix-sequential-mode-labels.md`
- [x] 06 — Simplify `parseToolUsage` for plain text output → `06-simplify-parsertoolsusage.md`
Dependencies
- 02 depends on nothing (standalone utils fix)
- 03 depends on 04 (needs ctx available in executor)
- 04 depends on nothing (standalone plumbing fix)
- 05 depends on 04 (executor changes)
- 06 depends on 02 (output format changes from --print)
Exit criteria
- `/ralph resume` runs without errors in a project with no `.ralph/config.yaml`
- Pi subprocess spawns successfully with `--print` mode
- Progress messages display via `ctx.ui` without TUI crash
- All batch execution paths receive context parameter