Skip to content

Fix incremental caller loss after re-exported symbol rename - #1062

Merged
11 commits merged into
tirth8205:stagingfrom
vincedk-alt:codex/fix-incremental-reexport-invalidation
Nov 6, 2026
Merged

11 commits merged into
tirth8205:stagingfrom
vincedk-alt:codex/fix-incremental-reexport-invalidation

Conversation

@vincedk-alt

Copy link
Copy Markdown
Contributor

An incremental update after renaming an exported TypeScript function can lose callers in unchanged files that import through a re-export. The dependency walk finds those files, but the content-hash shortcut skips reparsing them, leaving edges pointed at the old symbol identity. A full rebuild finds all three callers; the incremental update finds only one.

Invalidate the discovered dependents when the seed file actually changed, while retaining the no-op shortcut for duplicate notifications. Reuse the hash read so parse-stage snapshot coherence is preserved.

Validation: the new synthetic rename/re-export regression fails on v2.3.9 and passes with this patch; all 140 incremental tests pass, including snapshot-race coverage. No application source is included.

tirth8205 and others added 11 commits September 16, 2026 20:50
Bound tool calls and optimize change discovery process
Bound tool calls and optimize change discovery process
Improve test gap reporting and caller reachability classification
Improve test gap reporting and caller reachability classification
Release version 2.3.9 with schema updates and documentation fixes
Release v2.3.9 with schema updates and documentation fixes
@tirth8205

Copy link
Copy Markdown
Owner

Thank you for this PR. I tested renames through re-exports with update, watch and the MCP tool. The fix works for those cases.

Before I can merge it, please fix these:

  1. Re-parsing unchanged importers loses their flows and communities. Update post-processing only refreshes result["changed_files"]. The forced dependents get new node ids, so their flows and community ids break. Where: code_review_graph/incremental.py:2041 and code_review_graph/tools/build.py:750. Example: add a comment to fee.ts, then run update. The flow main in use.ts now has no steps. Test: test_comment_edit_to_imported_module_keeps_importer_flows_and_communities.

  2. The new hash check reads every changed file in full. This includes big data files the graph never indexes. Where: code_review_graph/incremental.py:1978. Please hash only when existing has nodes. Example: a tracked 64 MB data file with a local change. Test: test_update_does_not_read_changed_unindexed_data_file.

Please also point the PR at staging, not main.

The failing tests are on the branch review/pr-1062 in this repo. You can copy them from there. If a test there is marked xfail, please remove that mark with your fix.

After you push the fix, I will test it again.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

A transient dependent read or parse failure can leave renamed-symbol caller edges indefinitely stale because subsequent updates fail to retry the unchanged dependent.

3 open issues
What changed in this PR

This PR addresses caller loss during incremental graph updates after a TypeScript export is renamed, bringing unchanged re-export callers in line with full rebuild results.

Changes:

  • Reparse discovered dependents when a seed file’s content changes.
  • Preserve duplicate-notification shortcuts and reuse cached hashes.
  • Add a regression comparing incremental and full-build callers and checking no-op replay.
File Description
tests/​test_incremental_reexport_regression.py Tests renamed exports, unchanged re-export callers, and duplicate notifications.
code_review_graph/​incremental.py Makes dependent invalidation sensitive to seed content changes and bypasses dependent hash shortcuts.

Review effort: Balanced

Comment on lines +1980 to +1981
if existing and existing[0].file_hash == current_hash:
continue
existing = store.get_nodes_by_file(full_path)
try:
current_hash = current_hashes.get(normalize_file_path(rel_path))
if current_hash is None:
(tmp_path/name).write_text(files[name].replace('calculateFee', 'computeFee'))
result = incremental_update(tmp_path, store, changed_files=['fee.ts', 'barrel.ts', 'client.ts'])
assert not result['errors']
target = str(tmp_path/'fee.ts') + '::computeFee'
@tirth8205
tirth8205 changed the base branch from main to staging November 6, 2026 12:14
@tirth8205 tirth8205 closed this pull request by merging all changes into tirth8205:staging in 0160eb0 Nov 6, 2026
gowrishacv pushed a commit to gowrishacv/code-review-graph that referenced this pull request Nov 6, 2026
…ters (review of tirth8205#1062)

Re-parsing an importer with unchanged bytes now replaces only its edges, so its
flows and communities survive at every post-processing level. Only files with
graph rows are hashed. A forced re-parse that fails is retried by the next
update. Adds the maintainer's review tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gowrishacv pushed a commit to gowrishacv/code-review-graph that referenced this pull request Nov 6, 2026
# Conflicts:
#	code_review_graph/incremental.py
#	code_review_graph/tools/build.py
gowrishacv pushed a commit to gowrishacv/code-review-graph that referenced this pull request Nov 6, 2026
Ruby methods always carry their full lexical scope (tirth8205#933), so the leaf
collision index from tirth8205#1087 now covers Python only, and the docs and tests say
so. Generators are not component wrappers' functions (tirth8205#972 with tirth8205#1131). Partial
graph coverage counts tracked files only (tirth8205#881 with tirth8205#1094). A pending marker
recomputes all derived data (tirth8205#1105), so that test starts from a finished graph,
the deleted-seed case now passes (tirth8205#1062 with tirth8205#673), and hooks.json keeps its
events under a hooks key (tirth8205#1102 with tirth8205#1126).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants