Skip to content

detect_changes: seed_symbols scoped to whole file, not the changed line range #1363

Description

@lishixiang0705

Problem

detect_changes's "seed" set (the symbols it treats as directly changed, before
running the blast-radius traversal) is computed at whole-file granularity,
not at the diff-hunk/line level. A one-line, single-statement edit inside one
method reports every definition in that file as a seed symbol, then runs the
blast-radius traversal from all of them — producing an impact report an order
of magnitude larger than what actually changed.

This contradicts the stated intent in #1154 ("It now resolves the git diff
to those symbols and runs one multi-source BFS ... to the transitive
impact set") — the BFS traversal is real, but the input to it (seed_symbols)
is not scoped to the touched lines.

Reproduction

Tested on microsoft/qlib @ 3097dcc9 (any repo with more than one definition
per file should reproduce this; the two cases below were chosen for very
different file sizes to rule out coincidence).

codebase-memory-mcp cli index_repository --repo-path <qlib-checkout> --mode full --name repro

Case Aqlib/log.py (24 top-level/class-member definitions):

# single-line in-place edit inside TimeInspector.logt(), no line-count change
sed -i '' 's/            pass/            cls.timer_logger.debug("x")/' qlib/log.py
codebase-memory-mcp cli detect_changes --project repro --format json --depth 1
{"seed_symbols": 25, "impacted_total": 141, ...}

25 = 24 definitions + 1 module node. Only logt was edited; the other 23
definitions in the file are untouched.

Case Bqlib/backtest/decision.py (42 definitions), same methodology,
one line replaced with itself plus a trailing comment (no line-count change,
touches exactly one return statement in one method):

sed -i '' '96s/.*/        return self.amount * self.sign  # bench-marker/' qlib/backtest/decision.py
codebase-memory-mcp cli detect_changes --project repro --format json --depth 1
{"seed_symbols": 43, "impacted_total": 68, ...}

43 = 42 definitions + 1 module node.

Both cases reproduce the same formula — seed_symbols == (definitions in changed file) + 1 — regardless of file size or which single line was
touched, which rules out this being an artifact of one file's structure.

Expected Behavior

seed_symbols should be the symbol(s) whose line range actually overlaps the
diff hunk (e.g. just logt for Case A, just the one method for Case B), not
every definition in the file.

Actual Behavior

Every definition in the changed file is treated as a seed, so the blast-radius
BFS runs from all of them. In Case A, the true direct callers of logt (6,
confirmed via oracle cross-check) were present in the output but diluted
across 141 total impacted entries pulled in by the other 23 unrelated seeds.

Impact

For any file with more than a handful of definitions, detect_changes on a
single-line change reports an impact set dominated by symbols the edit never
touched. This makes the tool unusable as a precision impact-review aid without
manual filtering — the caller has to guess which of the N seeds is the one
they actually meant.

Environment

  • codebase-memory-mcp 0.9.1-rc.1
  • macOS (Apple Silicon)
  • Reproduced twice on two files of very different size (24 and 42 definitions)
    with identical seed_symbols = defs_in_file + 1 in both

Suggested Fix

Scope seed identification to the definition(s) whose [start_line, end_line]
range intersects the diff hunk's changed line range, rather than every
definition record associated with the changed file path.

Metadata

Metadata

Assignees

No one assigned

    Labels

    parsing/qualityGraph extraction bugs, false positives, missing edges

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions