Repository navigation
fix: don't point the Ralph @fix_plan.md watcher at a remote session's directory - #722
Conversation
… directory A remote-SSH session's workingDir is a path on the remote host, but setupSessionListeners() handed it to the Ralph tracker, whose RalphFixPlanWatcher reads and fs.watch()es it on the LOCAL disk. Where the path does not exist locally (the usual case), every server start logged [RalphFixPlanWatcher] Could not watch @fix_plan.md: Error: ENOENT ... once per remote session; where a same-named local directory did exist, it watched the wrong tree. Setting the path also made the tracker treat that unreadable file as authoritative (isFileAuthoritative is "a path is set"), which switched off its output-based todo completion for remote sessions. Skip the tracker's working dir for remote sessions, next to the existing external-CLI skip.
|
Thank you @timkjr, and welcome! This PR stops the Ralph tracker from pointing its I checked every path that wires a session (create, Nothing needs to change on your side. The only touches at merge time are a one-line docs note that the The two follow-ups you listed (the |
Note in docs/remote-sessions.md that the @fix_plan.md auto-load does not run for remote sessions, and rewrap the test's header comment. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…her at a remote session's directory
…722) #722 stopped handing a remote session's workingDir to the Ralph tracker, which also left isFileAuthoritative false for remote sessions only. That flag is what keeps the output-based completion guessers off, and it is true for every local session with a working directory, so a remote loop could end, and mark every todo done, on a prose line such as "All tasks completed" while a local one cannot. setRemoteWorkingDir() records the path without reading or watching the local disk, so the fix plan stays authoritative as for a local session; the file still reaches the tracker only through fix-plan/read, over ssh. The test pins both, and fails on the previous head. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…eview, #722) setRemoteWorkingDir() records the path for authority only, and today nothing else reads it for a remote session (loadFixPlanFromDisk's only callers are setWorkingDir and the local watcher). The watcher now remembers the remote mode and refuses both the local read and the local watch for it, so a future caller cannot import a same-named local twin. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Merged in 1.47.0 (https://github.com/Ark0N/Codeman/releases/tag/codeman%401.47.0). Thank you for tracking this down from a real log line. At merge I added the note to |
What
setupSessionListeners()hands every non-external session'sworkingDirto the Ralph tracker (session.ralphTracker.setWorkingDir). For a remote-SSH session that directory is a path on the remote host, butRalphFixPlanWatcherreads andfs.watch()es it on the local disk. The Ralph tracker auto-enables on pattern detection, so this runs for remote sessions whether or not the user ever turned Ralph on.Observed on a server with two remote sessions on another host, once per remote session at every server start:
Two side effects beyond the log noise:
isFileAuthoritativeis_fixPlanPath !== null, so setting a path that can never be read made the fix-plan file "authoritative" for every remote session, which switched off the tracker's output-based todo completion (detectAllTasksComplete/detectTaskCompletionreturn early).Fix
One condition next to the existing external-CLI skip in
src/web/server.ts:Every path that wires a session (create,
/interactive,/interactive-respawn,/shell, reboot restore) goes throughsetupSessionListeners(), and restore rehydratessession.remotebefore it runs, so the one guard covers them all. Docker-case sessions are unchanged: theirworkingDiris the host-side workspace, which is local.Tests
test/ralph-fix-plan-remote.test.tsdrives the realWebServer.setupSessionListeners()(same pattern asdiscard-partially-built-session.test.ts):Could not watch @fix_plan.md, andisFileAuthoritativestaysfalse(fails on master: the remote path is passed tosetWorkingDir);npm run typecheck,lint,format:checkand the fullnpm testpass locally.Not covered here (same root cause, left for separate PRs if wanted)
These also treat a remote session's
workingDiras a local path:POST /api/sessions/:id/fix-plan/writeandGET .../fix-plan/read(ralph-routes.ts) read and write@fix_plan.mdon the local disk;imageWatcher.watchSession(session.id, session.workingDir)a few lines below the fix (quiet, because chokidar waits on a missing path, but it would report local files if the same path exists locally).🤖 Generated with Claude Code