fix(cursor): centralize platform-aware Cursor storage path resolution - #740
Draft
beruro wants to merge 1 commit into
Draft
fix(cursor): centralize platform-aware Cursor storage path resolution#740beruro wants to merge 1 commit into
beruro wants to merge 1 commit into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
agent_cli::cursor::pluginsre-implemented Cursor storage path resolution with a macOS-only layout and, when$HOMEwas 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. Meanwhileorgtrack_core::sources::cursor_ide::iocarried 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::cursorand make both consumers call it:app-pathsis the workspace's designated leaf crate for path resolution ("single source of truth shared by every workspace crate"), bothagent_cliandorgtrack_corealready depend on it, and theORGII_EXTERNAL_HISTORY_HOMEoverride 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.)~/Library/Application Support/Cursor/...; Linux$XDG_CONFIG_HOME/Cursor/...(absolute values only, per XDG spec) with~/.configfallback; Windows%APPDATA%\Cursor\...with<home>\AppData\Roamingfallback. The~/.cursor/plugins/cache/cursor-publicplugin cache stays home-anchored on every platform.ORGII_EXTERNAL_HISTORY_HOMEset, every path resolves deterministically beneath the override home and the real user's$HOME/XDG/%APPDATA%env is never consulted — identical contract toexternal_history_config_dir().Err(CursorPathsUnavailable)(implementsstd::error::Error); both call sites handle it explicitly and degrade to the "Cursor not installed" empty state./Users/_unknownis gone.CursorEnvsnapshot +Platformenum, so the full macOS/Linux/Windows matrix, override precedence, and missing-home cases are unit-tested on any host (13 new tests inapp_paths::cursor).Consumer changes:
orgtrack_core::cursor_ide::iodeletes its local matrix and delegates (publicOption+ existence-check contract unchanged);agent_cli::cursor::pluginsdeletesreal_user_db()/plugins_cache_dir()and delegates with explicit error handling.Potential risks
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.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..exists()check failed anyway); now it returnsNonedirectly — observably equivalent, but now typed.state.vscdbmatrices 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 ontoapp_paths::cursor.Verification
cargo test -p app_paths— PASS: 21 passed / 0 failed (includes the 13 newcursor::testscovering 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_paths— PASS (Finished dev profile in 4m 01s, no warnings surfaced).cargo test -p orgtrack_core -p agent_cli— NOT 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 warnings— NOT RUN: same time-box reason; deferring to CI.PR opened as Draft until CI confirms the NOT RUN items.