Skip to content

fix(cursor): centralize platform-aware Cursor storage path resolution - #740

Draft
beruro wants to merge 1 commit into
developfrom
junyu/fix-cursor-storage-paths
Draft

fix(cursor): centralize platform-aware Cursor storage path resolution#740
beruro wants to merge 1 commit into
developfrom
junyu/fix-cursor-storage-paths

Conversation

@beruro

@beruro beruro commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

Problem

agent_cli::cursor::plugins re-implemented Cursor storage path resolution with a macOS-only layout and, when $HOME was missing, silently fell back to the fabricated path /Users/_unknown. That yields wrong paths on Linux/Windows and a fake path instead of an explicit failure. Meanwhile orgtrack_core::sources::cursor_ide::io carried its own (more correct, override-aware) platform matrix — two divergent resolvers for the same on-disk locations.

Solution

Add a canonical resolver module app_paths::cursor and make both consumers call it:

  • Placement rationale: app-paths is the workspace's designated leaf crate for path resolution ("single source of truth shared by every workspace crate"), both agent_cli and orgtrack_core already depend on it, and the ORGII_EXTERNAL_HISTORY_HOME override semantics it must honor are already defined there (external_history_* family) — placing the resolver next to that definition removes the split-brain. (The task's alternative — extending orgtrack-core's resolver — was rejected because agent-cli→orgtrack-core would be a new, wrong-direction dependency edge.)
  • Platform matrix (baseline = orgtrack-core's existing matrix): macOS ~/Library/Application Support/Cursor/...; Linux $XDG_CONFIG_HOME/Cursor/... (absolute values only, per XDG spec) with ~/.config fallback; Windows %APPDATA%\Cursor\... with <home>\AppData\Roaming fallback. The ~/.cursor/plugins/cache/cursor-public plugin cache stays home-anchored on every platform.
  • Override semantics preserved: with ORGII_EXTERNAL_HISTORY_HOME set, every path resolves deterministically beneath the override home and the real user's $HOME/XDG/%APPDATA% env is never consulted — identical contract to external_history_config_dir().
  • Typed unavailability: missing home/config root returns Err(CursorPathsUnavailable) (implements std::error::Error); both call sites handle it explicitly and degrade to the "Cursor not installed" empty state. /Users/_unknown is gone.
  • Testable core: resolution is a pure function over a CursorEnv snapshot + Platform enum, so the full macOS/Linux/Windows matrix, override precedence, and missing-home cases are unit-tested on any host (13 new tests in app_paths::cursor).

Consumer changes: orgtrack_core::cursor_ide::io deletes its local matrix and delegates (public Option + existence-check contract unchanged); agent_cli::cursor::plugins deletes real_user_db()/plugins_cache_dir() and delegates with explicit error handling.

Potential risks

  • Linux/Windows edge-config behavior change (intended): orgtrack-core previously ignored XDG_CONFIG_HOME (Linux) and a relocated %APPDATA% (Windows), always joining under home. The canonical resolver now honors them, matching Cursor's actual Electron behavior. Users with default configs see no change.
  • agent-cli becomes override-aware (intended): under ORGII_EXTERNAL_HISTORY_HOME (multi-instance dev only), the plugins list now resolves beneath the override home instead of the real $HOME, consistent with all other external-Cursor-state discovery.
  • Missing-home edge: previously orgtrack-core would probe a temp-dir-derived fake path (whose .exists() check failed anyway); now it returns None directly — observably equivalent, but now typed.
  • Four more duplicated Cursor state.vscdb matrices exist outside this task's scope (key-vault/auto_detect/cursor.rs, git-api/commands/cursor_chat.rs, agent-core/providers/cursor_native/auth.rs, src/agent_sessions/.../cursor/usage/tracker.rs). Left untouched per single-responsibility; they are sweep candidates for a follow-up PR onto app_paths::cursor.

Verification

  • cargo test -p app_pathsPASS: 21 passed / 0 failed (includes the 13 new cursor::tests covering the 3-OS matrix, XDG/APPDATA precedence, override isolation, typed unavailability, filename joins, env-value filtering).
  • cargo check -p agent_cli -p orgtrack_core -p app_pathsPASS (Finished dev profile in 4m 01s, no warnings surfaced).
  • cargo test -p orgtrack_core -p agent_cliNOT RUN: run was interrupted twice by session limits and then dropped under an explicit 10-minute delivery time-box; CI runs the full suite. Change surface in these crates is two thin delegating call sites with unchanged signatures/contracts.
  • cargo clippy -p ... --all-targets -- -D warningsNOT RUN: same time-box reason; deferring to CI.

PR opened as Draft until CI confirms the NOT RUN items.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant