fix(incremental): scoped --update <subfolder> silently prunes the rest of the graph#1144
Open
tduong628 wants to merge 1 commit into
Open
fix(incremental): scoped --update <subfolder> silently prunes the rest of the graph#1144tduong628 wants to merge 1 commit into
--update <subfolder> silently prunes the rest of the graph#1144tduong628 wants to merge 1 commit into
Conversation
detect_incremental computed deletions as every manifest entry not found under the scanned root. Running --update on a SUBFOLDER of a larger corpus therefore reported the entire rest of the corpus as deleted; the --update driver forwards that list to build_merge(prune_sources=...), whose anti-shrink guard (safishamsi#479) is explicitly disabled while pruning, so the rest of the graph is wiped silently. A manifest entry now counts as deleted only when it is (a) within the current scan root's subtree AND (b) genuinely absent from disk. Out-of-scope entries, and entries still present on disk but skipped by detect() (sensitive/unsupported/excluded), are left untouched. Also adds realpath-based manifest matching so symlink / mount-alias path forms no longer cause false 'changed' or false 'deleted', and a loud (non-raising) warning in build_merge when a prune would remove a large share of the graph - the disabled anti-shrink guard is what made the original failure silent. Adds tests/test_incremental_scope_safety.py (4 cases).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
Running
graphify <subfolder> --updateon a subfolder of a corpus that is rooted higher up silently deletes every node outside that subfolder.detect_incremental()computes deletions as:current_filesonly contains paths under the scannedroot, so every manifest entry outsiderootis reported as deleted. The skill's--updateflow forwards that list straight tobuild_merge(prune_sources=...):…and
build_merge's anti-shrink safety check (#479) is explicitly skipped wheneverprune_sourcesis set, so there is no guardrail — the rest of the graph is wiped with no error.Repro
A graph built from a corpus root containing
memory/andtopics/. Later,graphify topics/ --updateto fold in one new topic file. Result: allmemory/nodes are reported deleted and pruned. (Hit this in practice: a scoped update on a topics folder reported ~250 unrelated nodes as deleted.)The fix
detect_incremental()now treats a manifest entry as deleted only when it is (a) inside the current scan root's subtree AND (b) genuinely absent from disk. Out-of-scope entries are simply not part of this incremental run, and entries still on disk but skipped bydetect()(sensitive / unsupported / excluded) are not deletions either.Two supporting changes:
..path-form drift no longer produces falsechangedor falsedeleted.build_mergewhen a prune would remove a large share of the graph — defense in depth, since the disabled anti-shrink guard is what made the original failure silent.Tests
New
tests/test_incremental_scope_safety.py(4 cases):No regressions:
test_detect.py,test_incremental.py,test_build.py→ 140 passed.