Summary
detect_changes correctly returns changed_files but always returns impacted_symbols: [] / impacted_count: 0 when the indexed project lives inside a git worktree (not the worktree root itself).
The root cause is that canonical_root is computed one level too high, causing a path prefix mismatch between git diff output and graph file paths.
Environment
- codebase-memory-mcp: v0.8.1
- OS: macOS 25.5.0 (Darwin)
- Project layout: git monorepo at
/workspace/, with sub-projects indexed from subdirectories (e.g., /workspace/scripts/, /workspace/runtime/solar-monitor/)
Repository Structure
/workspace/ ← actual git root (.git lives here)
├── scripts/
│ └── solar_daily_report_v1.py ← indexed as project "workspace-scripts"
├── runtime/
│ └── solar-monitor/ ← indexed as project "workspace-runtime-solar-monitor"
Steps to Reproduce
- Index a project whose
root_path is a subdirectory of the git worktree root (e.g., workspace/scripts/)
- Call
detect_changes with scope: "impact" and since: "HEAD~1"
{
"project": "Users-openclaw-.openclaw-workspace-scripts",
"since": "HEAD~1",
"scope": "impact",
"depth": 2
}
- Observe:
changed_files is correctly populated; impacted_symbols is []
Expected Behavior
impacted_symbols should list all symbols in the changed files plus their transitive callers.
Actual Behavior
{
"changed_files": ["scripts/solar_daily_report_v1.py", ...],
"changed_count": 120,
"impacted_symbols": [],
"impacted_count": 0,
"depth": 2
}
Root Cause
list_projects reveals the miscalculation:
{
"name": "Users-openclaw-.openclaw-workspace-scripts",
"root_path": "/Users/openclaw/.openclaw/workspace/scripts",
"git": {
"worktree_root": "/Users/openclaw/.openclaw/workspace",
"git_common_dir": "../.git",
"canonical_root": "/Users/openclaw/.openclaw/workspace/.."
}
}
| Field |
Value |
Notes |
| Actual git root |
/Users/openclaw/.openclaw/workspace/ |
confirmed via git rev-parse --show-toplevel |
canonical_root |
/Users/openclaw/.openclaw/ |
one .. too many |
| git diff path |
scripts/solar_daily_report_v1.py |
relative to actual git root |
| Expected path for matching |
workspace/scripts/solar_daily_report_v1.py |
relative to wrong canonical_root |
The path prefix that detect_changes strips from git diff paths (workspace/scripts/) does not match what the graph stored (solar_daily_report_v1.py relative to root_path), so no symbols are ever matched.
The symbol is present in the graph (verified via search_graph):
{
"name": "solar_daily_report_v1.py",
"qualified_name": "Users-openclaw-.openclaw-workspace-scripts.solar_daily_report_v1",
"label": "Module",
"file_path": "solar_daily_report_v1.py",
"out_degree": 81
}
The canonical_root appears to be computed as worktree_root + "/" + git_common_dir + "/.." which for git_common_dir = "../.git" resolves to workspace/../.git/.. = .openclaw/ instead of the correct workspace/.
Workaround
Currently falling back to manual trace_path + search_graph to assess blast radius for shared library changes.
Additional Notes
changed_files detection works correctly in all cases
- Projects indexed from the worktree root directly are unaffected
- Standalone git repos (not worktrees) are unaffected —
detect_changes works correctly there
- This affects all
Users-openclaw-.openclaw-workspace-* projects (anything inside the workspace)
Summary
detect_changescorrectly returnschanged_filesbut always returnsimpacted_symbols: []/impacted_count: 0when the indexed project lives inside a git worktree (not the worktree root itself).The root cause is that
canonical_rootis computed one level too high, causing a path prefix mismatch between git diff output and graph file paths.Environment
/workspace/, with sub-projects indexed from subdirectories (e.g.,/workspace/scripts/,/workspace/runtime/solar-monitor/)Repository Structure
Steps to Reproduce
root_pathis a subdirectory of the git worktree root (e.g.,workspace/scripts/)detect_changeswithscope: "impact"andsince: "HEAD~1"{ "project": "Users-openclaw-.openclaw-workspace-scripts", "since": "HEAD~1", "scope": "impact", "depth": 2 }changed_filesis correctly populated;impacted_symbolsis[]Expected Behavior
impacted_symbolsshould list all symbols in the changed files plus their transitive callers.Actual Behavior
{ "changed_files": ["scripts/solar_daily_report_v1.py", ...], "changed_count": 120, "impacted_symbols": [], "impacted_count": 0, "depth": 2 }Root Cause
list_projectsreveals the miscalculation:{ "name": "Users-openclaw-.openclaw-workspace-scripts", "root_path": "/Users/openclaw/.openclaw/workspace/scripts", "git": { "worktree_root": "/Users/openclaw/.openclaw/workspace", "git_common_dir": "../.git", "canonical_root": "/Users/openclaw/.openclaw/workspace/.." } }/Users/openclaw/.openclaw/workspace/git rev-parse --show-toplevelcanonical_root/Users/openclaw/.openclaw/..too manyscripts/solar_daily_report_v1.pyworkspace/scripts/solar_daily_report_v1.pyThe path prefix that
detect_changesstrips from git diff paths (workspace/scripts/) does not match what the graph stored (solar_daily_report_v1.pyrelative toroot_path), so no symbols are ever matched.The symbol is present in the graph (verified via
search_graph):{ "name": "solar_daily_report_v1.py", "qualified_name": "Users-openclaw-.openclaw-workspace-scripts.solar_daily_report_v1", "label": "Module", "file_path": "solar_daily_report_v1.py", "out_degree": 81 }The
canonical_rootappears to be computed asworktree_root + "/" + git_common_dir + "/.."which forgit_common_dir = "../.git"resolves toworkspace/../.git/..=.openclaw/instead of the correctworkspace/.Workaround
Currently falling back to manual
trace_path+search_graphto assess blast radius for shared library changes.Additional Notes
changed_filesdetection works correctly in all casesdetect_changesworks correctly thereUsers-openclaw-.openclaw-workspace-*projects (anything inside the workspace)