# fix(ruby): preserve suffixed method node IDs (#3077) - #3079
Conversation
There was a problem hiding this comment.
Graphify reviewed this change.
Worth a look — the grounded gate found no coupling regressions or blocking issues, but 2 advisory finding(s) below merit a look before merge.
Formal verification. No changes could be formally verified in this run.
Graphify review — findings
Encodes trailing Ruby method suffixes (!, ?, =) into node ID components (_bang/_pred/_eq) via a new _ruby_sanitize_method_name, so foo, foo!, foo?, and foo= get distinct, stable IDs instead of colliding, while keeping their raw .foo!() display labels. Wires this through _extract_generic with an optional sanitize_symbol_name_fn on LanguageConfig (defaults to identity for other languages) and applies it before the empty-name collision check. Fixes Ruby call resolution to index and look up methods by their raw suffixed name rather than the _key-normalized form, so a.save and a.save! resolve to separate targets.
Worth a look
- Ruby suffix sanitizer collides with legitimate method names —
graphify/extract.py:901· Escalate · medium- agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
- LanguageConfig positional constructor contract shifted —
graphify/extractors/models.py:50· Escalate · medium- agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
Analysis details — impact, health, verification
Impact & health
Graphify review
Impact — 2210 functions depend on the 1021 functions this change touches.
Health — this change adds coupling hotspots:
- new:
extract()— 491 callers, 42 callees - new:
_rebuild_code()— 98 callers, 50 callees - new:
_extract_generic()— 18 callers, 24 callees - new:
extract_xaml()— 19 callers, 17 callees - new:
dispatch_command()— 2 callers, 122 callees - new:
extract_objc()— 27 callers, 9 callees - new:
extract_js()— 80 callers, 3 callees - new:
_get_extractor()— 26 callers, 6 callees - …and 34 more — each is listed as a finding
Verification — 2210 functions in the blast radius were not formally verified this run (proofs are advisory here).
Gate & verification
graphify gate
PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.
Advisory (not blocking):
- verification_scope: 2059 function(s) in the blast radius were not formally verified this run
Formal verification
Could not verify: Could not verify \_extract\_generic.
The verifier did not have enough to check \_extract\_generic, so it is saying so rather than guessing. No false assurance is the whole point.
Guarantee: No guarantee either way, this is an honest abstention, not a pass.
Note: Reason: parameter `path` is annotated `Path` — outside the synthesizable primitive/collection set
Could not verify: Could not verify resolve\_ruby\_member\_calls.
The verifier did not have enough to check resolve\_ruby\_member\_calls, so it is saying so rather than guessing. No false assurance is the whole point.
Guarantee: No guarantee either way, this is an honest abstention, not a pass.
Note: Reason: non-vacuity: domain too small (only 1 distinct inputs exercised, need 3) — 'no divergence' would be near-vacuous
· 42 more finding(s) on lines outside this diff (see the check run).
|
Shipped in v0.9.50 via authorship-preserving cherry-pick so you keep contributor-graph credit. Thanks @hopstreax! Release: https://github.com/Graphify-Labs/graphify/releases/tag/v0.9.50 |
Summary
Fixes #3077.
Ruby methods such as
foo,foo!,foo?, andfoo=were previously normalized to the same node ID. When defined in the same class/file, the first method encountered by the extractor was retained and the others were silently dropped byseen_ids.This caused missing nodes and incorrect/missing call relationships for common Ruby bang, predicate, and setter methods.
What changed
Added an optional
sanitize_symbol_name_fntoLanguageConfig.Added Ruby-specific sanitization for trailing method suffixes:
!→_bang?→_pred=→_eqKept the global
normalize_id()/make_id()behavior unchanged.Preserved the original Ruby method spelling in node labels.
Updated Ruby member-call resolution to use the raw method spelling instead of stripping punctuation.
Added regression coverage for:
foo,foo!,foo?, andfoo=Example
Before:
Both methods normalized to the same node ID, causing
save!to be dropped.After:
Both methods are represented as distinct nodes while their labels retain the original Ruby spelling.
Validation
Focused Ruby/resolution tests:
ID normalization and extraction-spec contract tests:
Broader suite:
The two failures are unrelated Windows environment issues involving Unicode
cp1252encoding and deeply nested temporary paths.Global ID normalization and other language extractors remain unchanged.
Scope
This PR addresses Ruby suffixed method names (
!,?,=). Ruby operator-method handling is intentionally left out of this change.