Gate and fix data-flow name binding and change detection - #6
Merged
Merged
Conversation
Regression gate: semantic_cases.json gains `changes` and `name` data-flow checks (with allowedKinds and mustBeUnbound forms). Nine new cases, each with a contrasting check, fail on main and pass here. Fixes: - Module-level names resolve as module globals with their value, including inside top-level if/try blocks, plus implicit module attributes. - Names a nested function or lambda reads from its enclosing function are closure variables (LEGB order; class bodies are not enclosing). - `except ... as exc` is bound in its handler and unbound afterwards. - Comprehension and lambda variables stay inside their expression; tuple comprehension targets are bound. - Builtins used as values are labelled builtin. - Imports inside if/try/with blocks are indexed. - A callee calling only read-only methods on a parameter no longer marks the caller's argument as possibly changed. - self.items.append(item) records a change to self.items; the summary shows self/cls changes with their attribute. - A factory's return annotation (-> Repo, -> Optional[Repo]) types the receiver of its result. On agent-kanban-pm, unknown-name gaps in method data flow fall from 763 to 0 with no new data-flow errors. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Opening a method from search or a start page rendered it twice: startReview selected it, then building the call map selected the entry stage, which is the same method, and redrew the view. The second render briefly showed "Loading code…" and refetched source and data flow. Native Safari read the view during that window, failing method_review_default in CI. chooseScope now skips the redraw when the same snapshot and method are already rendered. A browser smoke check counts renders when opening a method; it fails on the old code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Summary
This adds a regression gate for method data flow first, then fixes what it catches. The gate follows review feedback: put the failing fixture cases into
semantic_cases.jsonbefore any more UI work.Regression gate
tests/semantic_cases.jsoncould only check call resolution.test_semantic_accuracy.pynow also runs two data-flow check kinds:"kind": "changes":mustChange/mustNotChangenames for a method."kind": "name": the node kind a name read must have (module_global,closure_variable,exception,builtin,import_reference,external). It also has anallowedKindsform (e.g. comprehension variables, which may leave no outside node) and amustBeUnboundform (e.g. a read after itsexceptclause).Nine new cases, each paired with a contrasting check so a fix can't pass by over-correcting:
self.items.appendchangesself.items-> Repo/-> Optional[Repo]types the receivertry, are module globalsexternalexcept … as excbindsexcexcafter thetryis unboundkey=str)lenwinstry/if, and__file__The new cases fail on
mainand pass here. The gate has 54 checks, with zero incorrect supported results.Fixes (
dataflow.py,analyzer.py)if/try/withblocks are indexed.except … as, comprehensions and lambdas bind their names only within their own scope.count,index,get,keys,startswith, …) no longer mark the caller's argument as possibly changed. Known mutators and unknown methods still do.self.items.append(item)records a change toself.items, and the summary chip showsself.itemsand highlights the lines that change it.Effect on a real codebase (agent-kanban-pm, 1,174 functions,
main→ this branch)Testing
python test_semantic_accuracy.py: 54 checks pass, 0 false supported.python -m pytest: 162 pass.tests/browser_smoke.pyin all four modes (live,--changes,--html,--html --changes): all pass.Not in this PR
🤖 Generated with Claude Code