fix: never read a remote fix-plan path from the local disk (release review, #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>
This commit is contained in:
Codeman maintainer committed 2026-10-28 09:34:05 +01:00
1 parent 9f7cba07ab
commit ca0f891c2b
2 files changed
+42 -4

No files matched your search

+33 -1
View File
@@ -18,7 +18,7 @@
* Drives the real `WebServer.setupSessionListeners()`, like
* discard-partially-built-session.test.ts.
*/
import { mkdirSync } from 'node:fs';
import { mkdirSync, rmSync, writeFileSync } from 'node:fs';
import { homedir } from 'node:os';
import { join } from 'node:path';
import { afterAll, afterEach, beforeAll, describe, expect, it, vi } from 'vitest';
@@ -100,6 +100,38 @@ describe('Ralph @fix_plan.md watcher and the session location', () => {
expect(session.ralphTracker.isFileAuthoritative).toBe(true);
});
it('never reads a same-named local file for a remote session', async () => {
// The remote path exists locally too (an sshfs mount, a leftover checkout) and holds a plan.
writeFileSync(join(WORKSPACE, '@fix_plan.md'), '- [ ] a local task the remote session never had\n');
try {
const session = new Session({
id: SESSION_ID,
workingDir: WORKSPACE,
mode: 'claude',
name: 'remote session over a local twin',
mux,
useMux: true,
remote: {
hostId: 'proxx',
label: 'proxx',
host: 'proxx.example.lan',
username: 'user',
remotePath: WORKSPACE,
owned: true,
},
});
vi.spyOn(console, 'log').mockImplementation(() => {});
await internals.registerSessionWithLayout(session);
await internals.setupSessionListeners(session);
expect(await session.ralphTracker.loadFixPlanFromDisk()).toBe(0);
expect(session.ralphTracker.todos).toEqual([]);
} finally {
rmSync(join(WORKSPACE, '@fix_plan.md'), { force: true });
}
});
it('keeps a remote session todo list out of the prose completion guessers', async () => {
const session = buildSession(true);
vi.spyOn(console, 'log').mockImplementation(() => {});