You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The on-disk index cache key hashes the raw source string the CLI/MCP receives, while the persisted manifest records the absolute path. Upstream semble canonicalizes before keying. Found while implementing csp clear orphans (#87).
Where
crates/csp/src/indexing/cache.rs::resolve_cache_dir → normalize_source(source) only runs a POSIX path.normalize (./../duplicate slashes). "." stays ".".
crates/csp/src/bin/csp/main.rsSearch arm: let source = path.unwrap_or_else(|| ".".to_string()) is passed to load_or_build_index verbatim. Same for MCP (mcp.rs::DiskLoadOrBuild, source as sent by the agent).
crates/csp/src/indexing/index.rs::from_path stores std::path::absolute(path) as root → manifest sourceId.
Cache-key collision across repos. Every csp search "q" (default .) in any repo resolves to the same~/.csp/index/<key>. Switching between repos makes the content-hash oracle mismatch and forces a full rebuild each time (the incremental reuse path is seeded from the other repo's manifest, so it reuses nothing useful either).
Same repo reached via ., ./, /abs/path, or ~/path produces separate cache entries.
Tasks
Canonicalize local sources before keying (std::path::absolute at minimum; consider canonicalize to fold symlinks — decide and document in ADR-0002). Git URLs stay verbatim.
Apply at one seam so CLI, MCP, and the SDK agree (load_or_build_index / resolve_cache_dir), and keep the manifest sourceId equal to the keyed form so clear orphans can regain upstream's key-reproduction guard.
Bump/cache-invalidate as needed: existing entries keyed from relative strings become unreachable (harmless, clear index / clear orphans cleans them).
Tests: . and /abs map to the same key; two different cwds with . map to different keys.
Summary
The on-disk index cache key hashes the raw source string the CLI/MCP receives, while the persisted manifest records the absolute path. Upstream semble canonicalizes before keying. Found while implementing
csp clear orphans(#87).Where
crates/csp/src/indexing/cache.rs::resolve_cache_dir→normalize_source(source)only runs a POSIXpath.normalize(./../duplicate slashes)."."stays".".crates/csp/src/bin/csp/main.rsSearcharm:let source = path.unwrap_or_else(|| ".".to_string())is passed toload_or_build_indexverbatim. Same for MCP (mcp.rs::DiskLoadOrBuild, source as sent by the agent).crates/csp/src/indexing/index.rs::from_pathstoresstd::path::absolute(path)asroot→ manifestsourceId.Upstream
cache.py::cache_key:Consequences
csp search "q"(default.) in any repo resolves to the same~/.csp/index/<key>. Switching between repos makes the content-hash oracle mismatch and forces a full rebuild each time (the incremental reuse path is seeded from the other repo's manifest, so it reuses nothing useful either).clear orphanscannot use upstream's key-reproduction guard. Upstream trusts an entry only whencache_key(root_path)reproduces the directory name. In csp that check never matches entries built from.or any relative path, so parity(#243): addcsp clear orphansto remove cached indexes whose source path no longer exists #87 dropped it and relies onis_git_url+ an absolute-sourceIdrequirement instead (see the PR for parity(#243): addcsp clear orphansto remove cached indexes whose source path no longer exists #87). Canonicalizing the key would let csp restore the upstream guard..,./,/abs/path, or~/pathproduces separate cache entries.Tasks
std::path::absoluteat minimum; considercanonicalizeto fold symlinks — decide and document in ADR-0002). Git URLs stay verbatim.load_or_build_index/resolve_cache_dir), and keep the manifestsourceIdequal to the keyed form soclear orphanscan regain upstream's key-reproduction guard.clear index/clear orphanscleans them)..and/absmap to the same key; two different cwds with.map to different keys.Refs
csp clear orphansto remove cached indexes whose source path no longer exists #87 (csp clear orphans) — where this was observedsrc/semble/cache.py::cache_key