Agent/IDE CLI config or sandbox directories some clients launch their MCP
server from, but which are never a user’s project root. Adopting one as the
project root jails every real repository path out — the root cause of #580
(GitHub Copilot CLI launches from ~/.copilot; Cursor, Windsurf, Gemini CLI
and LM Studio behave similarly). This is the canonical set: every “is this an
agent dir?” check across the codebase delegates here so the list never drifts.
SECURITY canonicalize: always resolves symlinks, even under ~/Documents in a
launchd-standalone process. PathJail relies on this to detect symlink jail
escapes (#356 must never weaken the security boundary). A standalone process
only reaches here for a path the client explicitly asked to access, where a
one-time TCC prompt is legitimate — unlike the self-initiated heuristic
probes that safe_canonicalize suppresses.
SECURITY variant of safe_canonicalize_bounded — bypasses the #356 TCC
guard so PathJail keeps resolving symlinks to detect jail escapes. See
canonicalize_secure for why a prompt here (explicit request) is legitimate.
Returns true if dir is — or lies inside — a known agent/IDE config dir
(AGENT_CONFIG_DIRS). Separator-agnostic so Windows backslash paths
(C:\Users\me\.copilot) match too; #580 is a Windows Copilot report.
Returns true if the directory is too broad to be a valid project root.
Rejects home directories (including WSL-mounted Windows profiles), filesystem
root, . (bare CWD), and agent/IDE config directories
(AGENT_CONFIG_DIRS). Used to prevent adopting a bogus project root and
writing project-scoped data into the global ~/.lean-ctx/ data directory.
Returns true if project_root collides with the lean-ctx data directory.
This prevents project-scoped files (overlays.json, policies.json) from being
written into ~/.lean-ctx/ or ~/.config/lean-ctx/.
Returns true if path lies inside (or is) one of the macOS TCC-protected
home folders (~/Documents, ~/Desktop, ~/Downloads). Pure string/path
comparison — performs no filesystem access itself.
Normalize paths from any client format to a consistent OS-native form.
Handles MSYS2/Git Bash drive prefixes on Windows hosts
(/c/Users/... -> C:/Users/...), mixed separators, double slashes, and
trailing slashes. Uses forward slashes for consistency. On non-Windows
hosts /c/... is a literal directory and passes through unchanged (#397).
Lexical (string-only) part of normalize_tool_path: MSYS2 drive prefix
(Windows hosts only), separators, double slashes, trailing slash. Performs
no filesystem access, so it is safe on persisted paths in
TCC-standalone processes (launchd daemon, #356) and as a dedupe key where
symlink resolution is not worth a realpath per entry.
Returns true when this process is its own TCC identity on macOS — i.e.
it was started (or re-parented) by launchd rather than by a
TCC-granted host like a terminal or an editor.
Canonicalize a path and strip the Windows verbatim/extended-length prefix (\\?\)
that std::fs::canonicalize adds on Windows. This prefix breaks many tools and
string-based path comparisons.
Canonicalize with a timeout guard. Protects against hangs on WSL2 DrvFS,
Windows reparse points, NFS, FUSE, sshfs, and other slow filesystems.
Falls back to the original path if canonicalize doesn’t complete within the timeout.
Self-healing: after a timeout, subsequent calls to slow mounts skip the thread entirely.