mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-20 09:09:35 +02:00
fix(worktrees): a session spelled through the case's symlink blocks removal
The removal guard and the per-worktree session count compared each session's workingDir lexically against the worktree paths git lists, which are real paths. POST /api/sessions stores workingDir as it was spelled, so a session started in a worktree of a linked case whose folder is a symlink (a repository on another disk, macOS /tmp, a symlinked cases folder), named through that link, counted for no worktree, and DELETE /api/cases/:name/worktrees/:worktree removed the folder under the running agent (reproduced: 200 instead of 409). Each session folder under the case path is now respelled onto the repository's real top level before the comparison (respellUnder, pure and lexical, so no filesystem call per session). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
3952963bad
commit
0ce6e09725
4 files changed
+85
-9
No files matched your search
@@ -21,6 +21,7 @@ import {
|
||||
removeCaseWorktree,
|
||||
resolveCaseRepository,
|
||||
resolveManagedWorktree,
|
||||
respellUnder,
|
||||
unquoteGitPath,
|
||||
worktreeBaseError,
|
||||
worktreeBranchError,
|
||||
@@ -103,6 +104,15 @@ describe('paths', () => {
|
||||
expect(isPathWithin('/r/.claude/worktrees/a/src', '/r/.claude/worktrees/a')).toBe(true);
|
||||
expect(isPathWithin('/r/.claude/worktrees/ab', '/r/.claude/worktrees/a')).toBe(false);
|
||||
});
|
||||
it('respellUnder moves a path named through the case link onto the real repository root', () => {
|
||||
expect(respellUnder('/link/.claude/worktrees/a', '/link', '/real')).toBe('/real/.claude/worktrees/a');
|
||||
expect(respellUnder('/link/.claude/worktrees/a/src/', '/link', '/real')).toBe('/real/.claude/worktrees/a/src');
|
||||
expect(respellUnder('/link', '/link', '/real')).toBe('/real');
|
||||
// Not under the alias (a segment match, never a string prefix), or no alias at all: unchanged.
|
||||
expect(respellUnder('/linked/x', '/link', '/real')).toBe('/linked/x');
|
||||
expect(respellUnder('/real/.claude/worktrees/a', '/link', '/real')).toBe('/real/.claude/worktrees/a');
|
||||
expect(respellUnder('/real/x', '/real', '/real')).toBe('/real/x');
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseWorktreeList', () => {
|
||||
|
||||
Reference in new issue
Block a user