Skip to content

detect_changes: impacted_symbols always empty for projects inside git worktrees (canonical_root miscalculated) #659

Description

@sisisleeping-web

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

  1. Index a project whose root_path is a subdirectory of the git worktree root (e.g., workspace/scripts/)
  2. Call detect_changes with scope: "impact" and since: "HEAD~1"
{
  "project": "Users-openclaw-.openclaw-workspace-scripts",
  "since": "HEAD~1",
  "scope": "impact",
  "depth": 2
}
  1. 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)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions