mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-05 15:09:42 +02:00
fix(omp): resolve claudeSessionId alias on boot-recovery reattach
Two bugs compounded to break continuation pinning on every real OMP case (only /tmp-based manual testing happened to work by coincidence): 1. startInteractive() had a second, unconditional claudeSessionId assignment after the mux branch that clobbered its correctly resolved value back to the session's own id on every mux path. 2. mangleOmpWorkingDir() assumed omp mirrors Claude Code's directory naming (home prefix kept), but omp actually strips $HOME first. findLatestOmpSessionId() was silently returning null for every case under ~/codeman-cases/, so resumeSessionId never resolved for any real case dir - only /tmp paths (outside $HOME) worked, which is every dir this feature was previously tested against. Verified live: killed and relaunched the omp-verify server process mid-session (plain reattach, pane stayed alive) and confirmed claudeSessionId now resolves to the real omp transcript uuid instead of the Codeman session's own id. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
54a930c80e
commit
ed983f898b
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* @fileoverview Tests for OMP session-id resolution from disk.
|
||||
*
|
||||
* Pins the home-relative directory mangling bug found 2026-08-27: omp
|
||||
* collapses a home-relative workingDir to its home-relative remainder BEFORE
|
||||
* dash-replacing (`/home/user/dev/foo` -> `-dev-foo`), unlike Claude Code's
|
||||
* `~/.claude/projects/*` convention (`-home-user-dev-foo`) this module was
|
||||
* originally written to mirror. Getting this wrong doesn't throw — it just
|
||||
* makes findLatestOmpSessionId() silently return null for every case under
|
||||
* $HOME (virtually all real Codeman cases), so continuation pinning quietly
|
||||
* degraded to omp's own ambiguous `--continue` while appearing to work in
|
||||
* manual testing done entirely under /tmp (which sits outside $HOME and was
|
||||
* mangled correctly by coincidence).
|
||||
*
|
||||
* test/setup.ts gives this file its own temp $HOME, so homedir() below is
|
||||
* already sandboxed — writing real files under it is safe and exercises the
|
||||
* exact home-relative path the bug hid behind.
|
||||
*/
|
||||
import { mkdirSync, rmSync, utimesSync, writeFileSync } from 'node:fs';
|
||||
import { homedir } from 'node:os';
|
||||
import { join } from 'node:path';
|
||||
import { afterEach, describe, expect, it } from 'vitest';
|
||||
import { findLatestOmpSessionId, mangleOmpWorkingDir } from '../src/utils/omp-session-resolver.js';
|
||||
|
||||
describe('mangleOmpWorkingDir', () => {
|
||||
it('strips the home prefix before dash-replacing a home-relative path', () => {
|
||||
const home = homedir();
|
||||
expect(mangleOmpWorkingDir(join(home, 'codeman-cases', 'testcase'))).toBe('-codeman-cases-testcase');
|
||||
});
|
||||
|
||||
it('dash-replaces a path outside $HOME as-is', () => {
|
||||
expect(mangleOmpWorkingDir('/tmp/omp-verify-case')).toBe('-tmp-omp-verify-case');
|
||||
});
|
||||
|
||||
it('treats workingDir === home as the empty remainder', () => {
|
||||
expect(mangleOmpWorkingDir(homedir())).toBe('');
|
||||
});
|
||||
|
||||
it('does not false-positive on a sibling directory sharing a prefix with $HOME', () => {
|
||||
const sibling = `${homedir()}-other/dev/foo`;
|
||||
expect(mangleOmpWorkingDir(sibling)).toBe(sibling.replace(/\//g, '-'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('findLatestOmpSessionId', () => {
|
||||
const sessionDir = join(homedir(), '.omp', 'agent', 'sessions', '-codeman-cases-testcase');
|
||||
|
||||
afterEach(() => {
|
||||
rmSync(join(homedir(), '.omp'), { recursive: true, force: true });
|
||||
});
|
||||
|
||||
it('finds the newest session file under a home-relative workingDir', () => {
|
||||
const workingDir = join(homedir(), 'codeman-cases', 'testcase');
|
||||
mkdirSync(sessionDir, { recursive: true });
|
||||
writeFileSync(join(sessionDir, '2026-08-27T17-15-57-989Z_older-id.jsonl'), '{}');
|
||||
const newer = join(sessionDir, '2026-08-27T17-31-08-001Z_newer-id.jsonl');
|
||||
writeFileSync(newer, '{}');
|
||||
// Force a deterministic mtime order regardless of filesystem timestamp resolution.
|
||||
const now = Date.now() / 1000;
|
||||
utimesSync(join(sessionDir, '2026-08-27T17-15-57-989Z_older-id.jsonl'), now, now);
|
||||
utimesSync(newer, now + 1, now + 1);
|
||||
|
||||
expect(findLatestOmpSessionId(workingDir)).toBe('newer-id');
|
||||
});
|
||||
|
||||
it('returns null when the mangled directory does not exist', () => {
|
||||
expect(findLatestOmpSessionId(join(homedir(), 'never-launched'))).toBeNull();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user