feat: selective relationship capture with READS_FROM/WRITES_TO I/O edges#638
feat: selective relationship capture with READS_FROM/WRITES_TO I/O edges#638vitali87 wants to merge 6 commits into
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces I/O capture capabilities to track reads and writes to external resources (like files, databases, and network endpoints) in Python codebases, adding a new Resource node and READS_FROM/WRITES_TO relationships. Feedback on the implementation highlights several areas for improvement: the AST traversal currently processes nodes in reverse order, which incorrectly resolves variable reassignments to their first rather than last assignment; it lacks support for tracking file handles opened via idiomatic with statements; and target resolution is limited to positional arguments, ignoring keyword arguments.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
Greptile SummaryThis PR adds selective graph relationship capture and opt-in Python I/O resource edges. The main changes are:
Confidence Score: 5/5This PR appears safe to merge. No accepted issues were found in the reviewed capture selection, filtering, I/O processing, protobuf, and test paths. No files require special attention.
What T-Rex did
Important Files Changed
Sequence Diagram%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant CLI as CLI/config
participant GU as GraphUpdater
participant FI as FilteringIngestor
participant CP as CallProcessor
participant IO as IOAccessProcessor
participant DB as Ingestor
CLI->>CLI: resolve_capture(CGR_CAPTURE + --capture)
CLI->>GU: GraphUpdater(capture)
GU->>FI: wrap raw ingestor with selection
GU->>CP: create processors with filtered sink + capture
CP->>IO: process_io_for_caller(caller, module, language)
IO->>IO: match sink/handle and enabled rels
IO->>FI: ensure Resource node + READS_FROM/WRITES_TO
FI->>DB: forward only enabled nodes/relationships
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant CLI as CLI/config
participant GU as GraphUpdater
participant FI as FilteringIngestor
participant CP as CallProcessor
participant IO as IOAccessProcessor
participant DB as Ingestor
CLI->>CLI: resolve_capture(CGR_CAPTURE + --capture)
CLI->>GU: GraphUpdater(capture)
GU->>FI: wrap raw ingestor with selection
GU->>CP: create processors with filtered sink + capture
CP->>IO: process_io_for_caller(caller, module, language)
IO->>IO: match sink/handle and enabled rels
IO->>FI: ensure Resource node + READS_FROM/WRITES_TO
FI->>DB: forward only enabled nodes/relationships
Reviews (4): Last reviewed commit: "fix: skip Resource node when its only I/..." | Re-trigger Greptile |
|
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
|
@greptile review |
|
@greptile review |
|
@greptile review |
What
Adds a selective relationship capture framework and ships
READS_FROM/WRITES_TOI/O edges as its first opt-in add-on (issue #51).I/O edges (
READS_FROM/WRITES_TO)Resourcenode (kind + literal-or-<dynamic>identity) and two relationship types.codebase_rag/parsers/io_access/: a curated per-language sink registry (open,requests.*,os.getenv,print,json.*,sqlite3, sockets…) plus resource-handle tracking (f = open(p,'w'); f.write(x),conn = sqlite3.connect(); conn.execute(sql)with SQL-keyword direction). Python first; the pipeline is language-agnostic so other languages are later registry tables.open()mode arg; target captured as a string literal when known, else collapsed to one<dynamic>resource per kind.Resourcemessage + oneof + enum values regenerated incodec/schema.proto/schema_pb2.py.Selective capture
structure,calls,types,imports,io. A build-time guard asserts everyRelationshipTypebelongs to exactly one group.io(and future add-ons) opt-in. Existing graphs are unchanged unless a user opts in.+TYPE/-TYPEoverrides,all/nonebases; dependency gaps (e.g. dropINHERITS, keepOVERRIDES) warn but are obeyed.FilteringIngestorchoke point (transparent passthrough that preserves each caller's exact call shape) wraps the ingestor insideGraphUpdater; the ~20 parser emission sites are untouched. The IO pass is additionally short-circuited when disabled.CGR_CAPTUREenv var (sticky baseline) + repeatable--captureflag onstart/index(per-run override), merged by one resolver.Tests
test_io_access_edges.py— direct sinks, handle tracking, direction refinement, dynamic targets, negative case.test_capture_resolver.py— default/opt-in/overrides/base tokens/dependency-gap/unknown-token.test_filtering_ingestor.py— enable/drop of rels and nodes, and call-shape preservation (positional vs keywordproperties).test_capture_end_to_end.py—GraphUpdater(capture=…)gates IO edges +Resourcenodes.ty+ruffclean.Usage
Closes #51.