100%

§04 impl ownership attribute nodes

Goal

Impl/method ownership and the suppression surface become repo-wide graph facts: per-facet CPG scope split (binder + comments repo-wide, CFG/DDG stay gated), HAS_METHOD densification, attribute/suppression nodes joined to Bug nodes.

Implementation Sketch

  • cpg_scopes.py grows per-facet prefix sets (SCOPE_BINDER, SCOPE_COMMENTS repo-wide; SCOPE_CFG_DDG unchanged); gen-cpg-scopes.py + build.rs codegen carries the split into main.rs; extractor_version + limitation_inventory_version bump (fingerprint invalidation understood).
  • binding.rs already scope-agnostic per-file for HAS_METHOD (deep-read fact) — widening is invocation scope, not new binder logic.
  • Attributes: new syn pass over item attributes; :Attribute{kind, reason, lint_name} + ON_SYMBOL; BUG-token join to :Bug enables DISPOSITION_DRIFT queries (TEST-21/22 class).

Spec References

  • intel_repo/neo4j/cpg_scopes.py + intel_repo/scripts/gen-cpg-scopes.py + extractor/cpg/build.rs (cross-language SSOT codegen); intel_repo/extractor/cpg/src/binding.rs; .claude/rules/impl-hygiene.md SPEC-03/60/61 (suppression audit), TEST-21/22 (disposition)

Work Items

  • Per-facet CPG scope split: binder/ownership + comments facets get their own scope knob (repo-wide) while CFG/DDG stay 5-prefix-gated; cpg_scopes.py + gen-cpg-scopes.py + main.rs plumbing; extractor_version bump + limitation-inventory update
  • HAS_METHOD/HAS_TYPE densification repo-wide via the widened binder facet; edge anchors documented per the contract registry (HAS_TYPE anchors Variable/Field, HAS_METHOD anchors Symbol(type))
  • Attribute/suppression nodes: #[allow]/#[expect]/#[ignore]/#skip/#derive as :Attribute nodes with reason props + ON_SYMBOL attachment; join #skip/#[ignore] reasons to :Bug nodes (BUG-XX-NNN token) for disposition-drift queries
  • Importer with per-file declarative diff for the new node classes; schema constraints + indexes applied; tests + probes (suppression-without-reason count, tracked-disposition join)

Fresh intel (regenerated)

This is a SCHEMA-DEEPENING section on the graph builder, and the single decisive fact is an architectural refactor of the CPG scope gate from ONE flat knob into PER-FACET knobs — because the facets have wildly different repo-wide cost. Today main.rs runs a single --scope-prefixes gate over ALL facets (5 prefixes, all under ori_arc::aims + 4 §14.1 sites). The heavy facets behind that gate are enormous — 312,923 DataFlowNode + 11,704 CfgBlock + 168,032 DEF_USE — and MUST stay gated. The light facets are tiny — 152 HAS_METHOD (100% confined to ori_arc), ~3,423 CodeComment — and are what goes repo-wide. You cannot widen “the scope”; you must SPLIT the gate so the binder + comments facets widen while CFG/DDG stay pinned. That split IS the section’s load-bearing deliverable, and it is the exact seam §06 comment-ingestion then consumes.

Second decisive fact: the :Attribute → :Bug disposition-drift join the section builds is HALF-LIVE today. The :Bug side exists and resolves — the 47 distinct BUG-XX-NNN tokens carried by compiler #skip/#[ignore] dispositions map onto real :Bug nodes with live statuses (open, in-progress). The :Attribute side is a genuinely NEW node class (:Attribute label does not exist; 0 nodes). The section supplies the missing endpoint; the query surface (TEST-21/TEST-22 disposition drift) lights up the moment it lands. [JOIN] The suppression population is concrete and sized: 97 #[allow] + 635 #[expect] + 62 #[ignore] + 899 #[derive] in compiler Rust, plus 117 #skip( in .ori tests (4 of them UNTRACKED — the exact TEST-21 red the fitness probe must catch).

Decisions this package forces before any code is written:

  1. Split the gate, don’t widen it. The per-facet knob (SCOPE_BINDER/SCOPE_COMMENTS repo-wide; SCOPE_CFG_DDG unchanged) is the design; a flat repo-wide widen would 100x the heaviest facets (§3.6). This is the whole architectural risk.
  2. Register the new classes in §01’s contract registry FIRST. §01 edge-class-contract (complete) is the rails: every node/edge class (:Attribute, ON_SYMBOL-for-attribute, the widened HAS_METHOD/HAS_TYPE, the :Bug join) MUST declare its registry row (identity/producer/prune/freshness/confidence) BEFORE first ingestion (§4, §3H).
  3. Preserve the SSOT codegen path. cpg_scopes.py → gen-cpg-scopes.py → cpg_scopes.rs is an existing LEAK:scattered-knowledge cure (§3H); the per-facet split must extend that ONE pipeline, never fork a second Python/Rust scope list.
  4. Bump the extractor fingerprint correctly. extractor_version + limitation_inventory_version bumps invalidate the CPG staleness fingerprint (§3D) — get this right or every downstream facet reads false-fresh.
  5. ON_SYMBOL is MATCH-not-fabricate. Per L10 (§3H), an attribute whose owning symbol is not a :Symbol node gets NO edge — never a fabricated anchor.

DIG DEEPER

python -m scripts.plan_corpus.read plans/intel-graph-deepening --completion   # section roster + statuses
python -m scripts.plan_corpus.read plans/intel-graph-deepening --section s-5389b01d --criteria

(full dossier: impl-ownership-attribute-nodes—s-5389b01d.intel.md)