Cross-file member-call resolution for C++/Objective-C (#1547/#1556) and namespace-aware C# type resolution (#1562), the work-memory overlay (#1441), and a batch of TS/JS/ObjC resolution + call-graph fixes.
- Feat: cross-file member-call resolution for C++ and Objective-C (#1547, #1556). A class declared in a header and defined in its
.cpp/.mno longer fragments into two nodes (a decl/def merge pass collapses the sibling header/impl pair, gated to same-directory same-name so unrelated classes never merge), and a member call now resolves across files by the receiver's inferred type: C++Foo f; f.bar()/Foo::bar()/this->bar()and ObjCFoo *f = [[Foo alloc] init]; [f doThing]/[self render]link to the owning class's method. Resolution is by receiver type, never bare name, with the single-definition god-node guard — an uninferable or ambiguous receiver produces no edge (high precision over recall, grounded in how compiler-free indexers like ctags/Doxygen mis-resolve by name). Also routes C++ headers to the C++ extractor and ObjC#importbridging headers to the ObjC extractor. Reported by @c0dezer019 and @JabberYQ. (Residual cross-file#includeedge resolution under symlinked roots and ObjC dynamic-dispatch receivers remain follow-ups.) - Feat: namespace-aware C# cross-file type resolution (#1562, thanks @TheFedaikin). The namespace is folded into the C# node id (so same-named types in different namespaces stay distinct),
usingdirectives are honored with lexical per-block scope, and qualified references (Namespace.Type,usingaliases) resolve — disambiguating a bare reference to the one in-scope namespace that provides it, and refusing (no edge) when ambiguous. Advances the #1318 shadow-node umbrella for C#. - Fix: test mocks no longer erase the real cross-file call graph (#1553, thanks @Schweinehund). When a bare callee name had 2+ definitions without unique import evidence, the god-node guard dropped the edge entirely — so a single same-named test mock wiped the real call graph (a 76-stub Pester suite erased everything). The guard now applies tie-breakers — non-test preference (a shared, segment-aware path classifier) then path proximity — and resolves only when exactly one candidate survives, else still bails. A real def plus a test mock resolves to the real def; two genuine non-test defs still bail (no fan-out).
- Fix: hyperedge member lists keyed
membersornode_idsare now accepted, not silently dropped (#1561, thanks @askalot-io). Normalized to the canonicalnodesat ingest (in build_from_json and semantic_cleanup), deduped, with a warning — mirroring the existing from/to edge-endpoint aliasing. - Feat: work-memory overlay —
graphify reflectnow projects the verdicts it distills (preferred / tentative / contested, recency-weighted) into a.graphify_learning.jsonsidecar next to graph.json, andgraphify explain/query/GRAPH_REPORT.md/ the HTML viewer surface them where you look (aLesson:hint, a colored node ring). Builds on the idea in #1441/#1542 (thanks @TPAteeq), implemented as a sidecar rather than stamping graph.json: structural truth stays separate (nolearning_*in graph.json or GraphML exports, no rebuild churn). Each verdict carries the source questions that produced it (provenance) and a content fingerprint of the cited code, so a verdict on a file that has changed since is flagged "code changed — re-verify" instead of shown as still-authoritative. Dead-ends stay query-scoped (a report section, never a node attribute). Letting verdicts influence query traversal is deliberately deferred (it needs propensity correction + exploration to avoid a self-reinforcing feedback loop). - Feat: type-aware
this.field.method()resolution for TypeScript/JS (#1316, thanks @guyoron1). A member call through a constructor-injected dependency (constructor(private db: Database)thenthis.db.query()) now produces acallsedge to the field type's method, resolved by the field's declared type and gated by the single-definition god-node guard (an ambiguous or untyped field produces no edge — no global name-match fan-out). EXTRACTED confidence; constructor parameter-property injection scope. - Feat: resolve TypeScript wildcard path aliases (#1544, thanks @oleksii-tumanov). A
compilerOptions.pathspattern like@app/*or@*/interfacesnow captures the matched segment and substitutes it into each target in order, honoring tsc's longest-prefix / exact-wins specificity, baseUrl, and the first-existing-target fallback. Extends the #1531 resolver. - Feat: resolve JS namespace re-export bindings (#1552, thanks @oleksii-tumanov).
export * as ns from './mod'now creates a real symbol node forns, registers it as a named export (so a downstreamimport { ns }resolves to it), and emits a file-levelre_exportsedge — treated as a single opaque binding, sons.memberaccesses don't fan out into false per-symbol edges. Includes cycle and deep-chain guards. - Feat: Objective-C dot-syntax property accesses and
@selector()call edges (#1475, #1543, thanks @guyoron1).self.product.namenow emits anaccessesedge and@selector(method)acallsedge, each resolved only to an unambiguous in-scope definition by exact method-id match (a sibling of the same class for dot-syntax; exactly one method by exact selector name for@selector) — soself.namecan't mis-resolve to a-surnamesibling and same-named methods across classes don't fan out. Completes the #1475 ObjC follow-ups.