§05 field read write edges
Goal
The writer/reader seam becomes queryable: a new field-use visitor pass (own namespace, never an L3-DDG extension) yields READS_FIELD/WRITES_FIELD, a bidirectional writers-of/readers-of surface, and turns the burden-registration probe green.
Implementation Sketch
- New visitor (ExprField lvalue/rvalue classification): WRITES_FIELD on assignment position, READS_FIELD on expression position; nodes keyed by synthetic id per CPG convention; CfgBlock containment attribution; deliberately NOT an extension of the FieldInitWalker or the L3 DDG (deepseek F7).
- Query surface: seam subcommand answering writers-of/readers-of for :Field owner_qn+name, traversing both directions.
- Probe: the burden-registration seam (register_user_burden -> burdens map <- TypeRegistry::burden -> lookup_burden callers) is the committed acceptance case.
Spec References
- intel_repo/extractor/cpg/src/binding.rs (FieldInitWalker boundary); intel_repo/CLAUDE.md L3/L6 limitations; the burden-registration seam: compiler_repo/compiler/ori_types/src/registry/types/mod.rs (register_user_burden, TypeRegistry::burden) + compiler_repo/compiler/ori_arc/src/lower/burden_lookup.rs
Work Items
- New syn visitor pass emitting field-use facts (READS_FIELD/WRITES_FIELD), gated repo-wide via the shared CPG_SCOPE_PREFIXES_BINDER_COMMENTS SSOT (matching FieldInitWalker/comments.rs/attributes.rs — never the narrower aims-scoped CPG_SCOPE_PREFIXES); WRITES_FIELD classification covers BOTH direct assignment positions (self.field = …) AND mutating method-call sites on the field receiver (.entry(…).insert(…)/.or_insert(…) and equivalent collection-mutation idioms) — a bare-assignment-only classifier misses the burden seam’s actual write site (write_spec_to_idx’s burden_by_signature.entry(…).insert(…)), which would silently break the section’s own acceptance probe; READS_FIELD on plain expression position; nodes keyed by synthetic id per CPG convention; CfgBlock line-containment attribution used WHERE a CfgBlock exists, degrading to enclosing-function/owner_qn attribution (MATCH-not-fabricate, per comments.rs L10 / s-916f0932 precedent) for out-of-CFG-scope files such as the burden-registration acceptance seam; deliberately NOT an extension of the FieldInitWalker or the L3 DDG (deepseek F7); extractor_version bump.
- Importer per the edge-class contract (per-file declarative diff, prune semantics declared); schema constraints; staleness rides the widened binder facet
- Writer/reader query surface: writers-of / readers-of subcommands (or one seam subcommand) resolving a field to its writer and reader method sets bidirectionally by keying on :Field owner_qn+name — NEVER on :CfgBlock, which has zero rows for out-of-aims-scope files such as the burden-registration acceptance seam; KNOWN_SUBCOMMANDS + blurbs.
- Burden-seam fitness probe green end-to-end (register_user_burden + write_spec_to_idx writers <-> TypeRegistry::burden + lookup_burden readers traversable both directions via the new writers-of/readers-of surface, appearing in scripts/intel-query.sh fitness —json’s corpus and reading green); add (a) a synthetic-fixture ingestion pin (READS_FIELD/WRITES_FIELD emitted for a self.f = x write, a self.f.entry(…).insert(…) mutating-call write, and a self.f read), (b) the live burden-seam bidirectional-traversal pin against the real graph, and (c) an L13 limitations-inventory entry documenting the CfgBlock-optional attribution plus the syntactic (non-type-aware) lvalue/rvalue classification boundary.
Fresh intel (regenerated)
This section adds a THIRD walker over the existing CPG substrate — a field-use pass emitting READS_FIELD/WRITES_FIELD on the already-repo-wide :Field nodes — deliberately NOT an extension of the two walkers that already touch fields (FieldInitWalker at binding.rs:326 produces constructor-site :FieldInit; DdgWalker at ddg.rs:67 produces lexical-name :DataFlowNode def/use). The one decisive constraint the graph surfaces: the acceptance seam lives OUTSIDE the CFG/DDG facet scope, so the walker’s “CfgBlock containment attribution” cannot be the primary key for the probe.
Decisions this package forces before any code is written:
:Fieldis ALREADY repo-wide (binder facet,CPG_SCOPE_PREFIXES_BINDER_COMMENTSempty = repo-wide) —TypeRegistry.burden_by_signature(line 47) +collection_burdens(line 69) exist as:Fieldnodes TODAY. The new facet MUST ride that same repo-wide binder gate (per work-itemw-61e261fc“staleness rides the widened binder facet”), NOT the aims-only CFG/DDG gate — else the burden seam has no field-use coverage.[JOIN]— see 3.3.- The CFG/DDG facet does NOT cover the seam:
MATCH (b:CfgBlock) WHERE b.file STARTS WITH 'compiler/ori_types/src/registry'returns 0. “CfgBlock containment attribution” therefore degrades to owner-qn attribution (the MATCH-not-fabricate patterncomments.rsL10 already uses) for out-of-CFG-scope files. Thewriters-of/readers-ofquery MUST key on:Field owner_qn+name, never on:CfgBlock.[JOIN]— see 3.4. - The “burdens map” in the section prose is a CONCEPT, not a field: the concrete fields are
burden_by_signature+collection_burdens+ the per-entrytypes_by_idx[*].burden. The probe must resolve writers-of BOTH storage homes (register_user_burden -> write_spec_to_idx side-table + reverse-index) and readers-of BOTH (TypeRegistry::burdenreads types_by_idx.burden OR collection_burdens; lookup_burden is the ori_arc reader). See 1 + 3.2. - The section has NO
depends_onand is independently workable; its siblings-916f0932(comment-ingestion-repo-wide) is the nearest structural precedent (a repo-wide binder-gated facet) — read it first. See 4.
["FieldInitWalker", "DdgWalker"]
DIG DEEPER
scripts/intel-query.sh status | python3 -c "import sys,json; r=[x for x in json.load(sys.stdin)['data']['repos'] if x['name']=='ori'][0]; print(r['facet_generations']['field-use'])"
sed -n '/## Code Property Graph/,/## Plan.Bug Graph Pipeline/p' intel_repo/CLAUDE.md | head -80
(full dossier: field-read-write-edges—s-16f6a8a2.intel.md)