Why
The ironic gap: CGR is written in Python, Python gets the deepest FLOWS_TO walk in the repo — and no semantic layer. Resolution rests on parsers/py/ heuristics (ast_analyzer.py 530, expression_analyzer.py 477, variable_analyzer.py 573 LOC) plus the shared name trie. Re-export chains, decorated callables, properties, and MRO dispatch are all approximated.
Plan — two stages, both behind the LanguageFrontend protocol
Stage 1: Jedi, in-process, zero toolchain
Jedi is pure-Python and needs no external binary — the cheapest semantic win in the whole roadmap:
- resolved_call_sites:
Script.infer()/goto() per call site — follows re-exports, class hierarchies, decorators, __init__.py aliasing
- external_sites: targets resolving into site-packages/stdlib → suppress fabricated first-party CALLS (the trie currently has no external proof for Python at all)
- expression_types: inferred types feeding
py/type_inference.py
Performance is the risk: Jedi is not fast on large repos. Mitigate with per-module memoization, resolving only call sites the heuristics marked ambiguous (the trie already knows when it fanned out), and a time budget that degrades to heuristics per module.
Stage 2: Pyright as the opt-in compiler-grade tier
Pyright is the ecosystem's de facto type authority and rides the same typeshed data stdlib_extractor.py already leans on. Run it as an LSP subprocess (pyright-langserver), issue textDocument/definition + hover for call sites, translate to the same fact families. Opt-in flag (PYTHON_FRONTEND: heuristic | jedi | pyright), node binary or pyright binary discovery, parser_fingerprint.py registration.
Tests
Fixture Python repo exercising: re-export chains (from .impl import f in __init__.py), @property and decorated functions, MRO dispatch across a diamond (cross-check with the existing method_override pass and the inheritance.py eval, which grades Python OVERRIDES against the ast oracle), a call into an installed third-party package (must become an external proof).
Depends on the LanguageFrontend protocol issue.
Why
The ironic gap: CGR is written in Python, Python gets the deepest FLOWS_TO walk in the repo — and no semantic layer. Resolution rests on
parsers/py/heuristics (ast_analyzer.py530,expression_analyzer.py477,variable_analyzer.py573 LOC) plus the shared name trie. Re-export chains, decorated callables, properties, and MRO dispatch are all approximated.Plan — two stages, both behind the
LanguageFrontendprotocolStage 1: Jedi, in-process, zero toolchain
Jedi is pure-Python and needs no external binary — the cheapest semantic win in the whole roadmap:
Script.infer()/goto()per call site — follows re-exports, class hierarchies, decorators,__init__.pyaliasingpy/type_inference.pyPerformance is the risk: Jedi is not fast on large repos. Mitigate with per-module memoization, resolving only call sites the heuristics marked ambiguous (the trie already knows when it fanned out), and a time budget that degrades to heuristics per module.
Stage 2: Pyright as the opt-in compiler-grade tier
Pyright is the ecosystem's de facto type authority and rides the same typeshed data
stdlib_extractor.pyalready leans on. Run it as an LSP subprocess (pyright-langserver), issuetextDocument/definition+hoverfor call sites, translate to the same fact families. Opt-in flag (PYTHON_FRONTEND: heuristic | jedi | pyright), node binary or pyright binary discovery,parser_fingerprint.pyregistration.Tests
Fixture Python repo exercising: re-export chains (
from .impl import fin__init__.py),@propertyand decorated functions, MRO dispatch across a diamond (cross-check with the existingmethod_overridepass and theinheritance.pyeval, which grades Python OVERRIDES against the ast oracle), a call into an installed third-party package (must become an external proof).Depends on the
LanguageFrontendprotocol issue.