Skip to content

astmap.changed_symbols treats diff hunk context lines as changed symbols #10

Description

@KumamuKuma

Summary

astmap.changed_symbols() can treat normal unified-diff context lines as changed lines. As a result, a proposal may claim that an untouched neighboring function or class was modified.

The false symbols are written into candidate intent and code_slices, so approved capsules can persist incorrect provenance and later graph edges can be built from the wrong (file, symbol) data.

How I tested

I tested isolated clones of several real GitHub projects, including:

  • pypa/sampleproject
  • python-humanize/humanize
  • pypa/packaging
  • theskumar/python-dotenv

For each Python repo I ran:

  1. rgit init
  2. append one tiny new top-level probe function
  3. rgit run -- python -c "print('accuracy=...')"
  4. inspect rgit pending --json

Evidence

In python-humanize/humanize, I only appended this new function to src/humanize/filesize.py:

def rgit_probe_humanize():
    return "humanize"

But the generated candidate said:

Changes to naturalsize, rgit_probe_humanize in src/humanize/filesize.py

naturalsize was only present as diff context and was not changed.

In pypa/packaging, I only appended:

def rgit_probe_packaging():
    return "packaging"

But the generated candidate said:

Changes to TimeMarkerSuite, rgit_probe_packaging, time_evaluate in benchmarks/markers.py

TimeMarkerSuite and time_evaluate were also only diff context.

Minimal reproduction

Start with m.py:

def old_context():
    return 1


def untouched_neighbor():
    return 2

Commit it, then append only:

def new_feature():
    return 3

The diff contains untouched_neighbor() as context:

@@ -4,3 +4,7 @@ def old_context():
 
 def untouched_neighbor():
     return 2
+
+
+def new_feature():
+    return 3

Actual changed_symbols(diff, repo) result:

[
  {"file": "m.py", "symbol": "new_feature"},
  {"file": "m.py", "symbol": "untouched_neighbor"}
]

Expected result:

[
  {"file": "m.py", "symbol": "new_feature"}
]

Likely cause

_changed_line_ranges() in src/rgit/astmap.py uses the full new-side hunk range from the hunk header:

result[current].append((start, start + max(length, 1) - 1))

But that range includes unchanged context lines. changed_symbols() should derive touched ranges from the actual diff body lines instead of treating the whole hunk as changed.

Impact

  • proposals can mention symbols that were not changed
  • capsule code_slices can contain false symbols
  • graph relationships such as overlaps can be created from incorrect symbol data
  • recall/compose can later use misleading capsule context

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions