Skip to content
This repository was archived by the owner on May 28, 2026. It is now read-only.
This repository was archived by the owner on May 28, 2026. It is now read-only.

Windows: hook path boundary guards fail due to Windows vs POSIX path format mismatch #141

Description

@psmux

Environment

  • OS: Windows 11
  • Shell: PowerShell 7 (default shell in psmux)
  • psmux: v3.3.2 (tmux compatible multiplexer for Windows)
  • overstory cli: v0.9.3
  • Claude Code: latest

Problem

The PreToolUse hook scripts deployed by hooks-deployer.ts use bash case pattern matching against $OVERSTORY_WORKTREE_PATH to enforce worktree path boundaries. On Windows, this path is always in Windows format (e.g. C:\cctest\agharness\.overstory\worktrees\my-agent) because git worktree add returns Windows paths natively.

However, the hook scripts are bash and may receive file paths in Unix format (/c/cctest/agharness/...) depending on how Claude Code resolves them through Git Bash. This causes the case match to always fail:

# OVERSTORY_WORKTREE_PATH = "C:\cctest\agharness\.overstory\worktrees\my-agent"
# FILE_PATH might be "/c/cctest/agharness/.overstory/worktrees/my-agent/src/main.rs"

case "$FILE_PATH" in "$OVERSTORY_WORKTREE_PATH"/*) exit 0 ;; esac
# ^ never matches because C:\... != /c/...

This blocks all Write, Edit, and Bash file modification hooks, making the agent unable to write any files inside its own worktree. The agent itself reports:

The Write/Edit/Bash file write hooks are broken on this Windows+Git Bash setup because $OVERSTORY_WORKTREE_PATH is a Windows style path (C:...) but bash file paths are Unix style (/c/...), causing all path boundary checks to fail.

Root Cause

In src/agents/hooks-deployer.ts, both buildPathBoundaryGuardScript() and buildBashPathBoundaryScript() use raw $OVERSTORY_WORKTREE_PATH in a bash case statement without normalizing the path format. On Windows, the env var holds a native Windows path but the bash environment may present file paths in POSIX format.

The env var is set in src/commands/sling.ts (lines ~925 and ~1016) using the return value of createWorktree(), which returns platform native paths.

Suggested Fix

Add a cygpath normalization at the top of each hook script, right after the OVERSTORY_AGENT_NAME guard:

# Normalize Windows paths to POSIX format when running under Git Bash / MSYS2
OVERSTORY_WORKTREE_PATH=$(cygpath -u "$OVERSTORY_WORKTREE_PATH" 2>/dev/null || echo "$OVERSTORY_WORKTREE_PATH");

This converts C:\cctest\agharness\... to /c/cctest/agharness/... when cygpath is available (Git Bash, MSYS2), and is a no op on Linux/macOS where cygpath does not exist.

The same normalization should also be applied to $FILE_PATH after extraction, since it could arrive in either format:

FILE_PATH=$(cygpath -u "$FILE_PATH" 2>/dev/null || echo "$FILE_PATH");

Affected Functions

  • buildPathBoundaryGuardScript() in src/agents/hooks-deployer.ts (line ~109)
  • buildBashPathBoundaryScript() in src/agents/hooks-deployer.ts (line ~388)

Reproduction

  1. On Windows, install psmux (tmux compatible multiplexer)
  2. Run: ov sling some-task --runtime claude --name my-agent
  3. The agent launches but all Write/Edit hooks fail with path boundary violations
  4. The agent falls back to workarounds like git cherry-pick to modify files

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:infrastructureHooks, guard rules, worktree management, CLI frameworkdifficulty:moderateRequires understanding of 1-2 subsystemsfocus:windowsWindows/WSL2 support (mprocs, psmux, SessionBackend abstraction)priority:highSignificant improvement, clear path to implement

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions