You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
follow-up: receiver-type-aware invoked-property matching to reduce dead-code false negatives #2088
collectInvokedPropertyNames (src/domain/graph/builder/call-resolver.ts, mirrored as collect_invoked_property_names in crates/codegraph-core/src/domain/graph/builder/stages/build_edges.rs) adds a property name to its evidence set whenever ANY call in the processed files has a non-empty receiver and that name — with no check that the receiver is plausibly the same dispatch-table object referenced by the object-literal being evaluated. A completely unrelated logger.resolve() or promise.resolve() call anywhere in the codebase will add resolve to the set and prevent { resolve: neverCalled } from being flagged dead, even if the actual dispatch table is never read.
This is the conservative error direction (false negative for dead-code — it can never misclassify genuinely live code as dead), so it was accepted as-is for #2034: that PR's stated scope was "require any invocation evidence" as a deliberately coarse "one hop further" heuristic (see the doc comment on collectInvokedPropertyNames), not precise receiver-type correlation. Tightening it now would require:
Extending the existing points-to/type-map machinery to track each receiver call site's inferred type/binding.
Correlating that inferred type back to the specific object-literal (or dispatch-table variable) that defines the property being checked.
Implementing this identically in both the WASM/TS and native Rust engines, per this repo's dual-engine parity requirement.
That's a nontrivial dataflow precision improvement, not a small tweak, so it's being tracked separately rather than folded into #2034's narrower "any evidence at all" fix.
What the fix entails: teach collectInvokedPropertyNames/resolveFallbackTargets (and their Rust mirrors) to only count a x.name(...) call as evidence for a given object-literal's { name: fn } property when x's resolved type/binding plausibly refers to that same object (e.g. via the existing typeMap/points-to infrastructure), rather than matching on bare property name alone.
Confirmed the issue's characterization is still accurate against current main (post-#2087): collectInvokedPropertyNames (src/domain/graph/builder/call-resolver.ts) and its Rust mirror collect_invoked_property_names (crates/codegraph-core/src/domain/graph/builder/stages/build_edges.rs) still add a property name to the evidence set whenever ANY call anywhere in scope has a non-empty receiver, with zero correlation between that receiver's inferred type and the specific object-literal/dispatch-table variable the property check is actually being evaluated against.
Why this isn't implemented in this pass
This is a genuine dataflow-precision feature, not a bug fix or plumbing change — and it's asymmetric with the other #2034-deferred follow-ups (#2086, #2087) in an important way: those were correctness bugs (the registry produced actively wrong — false-positive — call edges). This one is the opposite: the current behavior is conservative (a false negative for dead-code detection; it can never misclassify genuinely live code as dead), so nothing downstream is producing incorrect results today. It's a recall improvement to an advisory command (roles --role dead), not a soundness bug in the graph itself.
Actually closing the gap requires real algorithm design, not a wiring fix:
Extending the points-to/type-map machinery to track, per call site, which object-literal/dispatch-table instance a receiver plausibly refers to (not just its nominal class/type name — a bare { resolve: fn } returned from a factory has no name to match against, so this needs value-identity tracking through the existing points-to solver, or a new mechanism).
Correlating that instance-level binding back to the specific literal declaring the property under test.
The usual dual-engine parity burden: identical semantics in both the WASM/TS points-to solver and the native Rust one, each independently verified.
I looked for a narrower, bounded partial fix (e.g. an exclusion list for common non-dispatch-table receiver names like promise/logger) and decided against it — that trades one unprincipled heuristic for another (a hardcoded name list needing perpetual tuning, exactly the kind of ad-hoc special-casing this repo's conventions steer away from) without actually implementing the receiver-type correlation the issue asks for.
No change made. Leaving open — the fix direction in the issue body remains accurate and actionable for whoever picks this up with room to design the points-to extension properly.
Applying the blocked label so this issue stops consuming a /fixer batch slot on every future pass while it remains what it was diagnosed as above: a genuine points-to/dataflow algorithm-design project, not a bounded bug fix or plumbing change. Remove the label whenever someone is ready to design the receiver-instance correlation extension described above.
Activity
carlos-alm commentedon Aug 7, 2026
Investigated as part of a
/fixerpass.Confirmed the issue's characterization is still accurate against current
main(post-#2087):collectInvokedPropertyNames(src/domain/graph/builder/call-resolver.ts) and its Rust mirrorcollect_invoked_property_names(crates/codegraph-core/src/domain/graph/builder/stages/build_edges.rs) still add a property name to the evidence set whenever ANY call anywhere in scope has a non-emptyreceiver, with zero correlation between that receiver's inferred type and the specific object-literal/dispatch-table variable the property check is actually being evaluated against.Why this isn't implemented in this pass
This is a genuine dataflow-precision feature, not a bug fix or plumbing change — and it's asymmetric with the other #2034-deferred follow-ups (#2086, #2087) in an important way: those were correctness bugs (the registry produced actively wrong — false-positive — call edges). This one is the opposite: the current behavior is conservative (a false negative for dead-code detection; it can never misclassify genuinely live code as dead), so nothing downstream is producing incorrect results today. It's a recall improvement to an advisory command (
roles --role dead), not a soundness bug in the graph itself.Actually closing the gap requires real algorithm design, not a wiring fix:
{ resolve: fn }returned from a factory has no name to match against, so this needs value-identity tracking through the existing points-to solver, or a new mechanism).I looked for a narrower, bounded partial fix (e.g. an exclusion list for common non-dispatch-table receiver names like
promise/logger) and decided against it — that trades one unprincipled heuristic for another (a hardcoded name list needing perpetual tuning, exactly the kind of ad-hoc special-casing this repo's conventions steer away from) without actually implementing the receiver-type correlation the issue asks for.No change made. Leaving open — the fix direction in the issue body remains accurate and actionable for whoever picks this up with room to design the points-to extension properly.
carlos-alm commentedon Aug 7, 2026
Applying the
blockedlabel so this issue stops consuming a /fixer batch slot on every future pass while it remains what it was diagnosed as above: a genuine points-to/dataflow algorithm-design project, not a bounded bug fix or plumbing change. Remove the label whenever someone is ready to design the receiver-instance correlation extension described above.carlos-alm commentedon Aug 24, 2026
claiming issue-2088 (plan, via /oversee) — docs/plan-issue-2088
docs: fix WU-2b's return-owner escape gap and WU-5a's fabricated cita…
docs: fix issue-2088 plan's condition-4 reassignment gap (round 13)
docs(plan): pin exportedNames derivation, fix round-25 false claims (#…
docs(plan): fix callerName derivation, pts null-guard, and definition…
docs(plan): complete B1 with a widened enclosing-scope probe set (rou…
docs(plan): expand collision write-up, add shape 36, note this-receiv…
docs(plan): fix callerName derivation, pts null-guard, definitionName…
docs(plan): complete B1 with a widened enclosing-scope probe set (rou…
docs(plan): expand collision write-up, add shape 36, note this-receiv…
carlos-alm commentedon Sep 3, 2026
claiming issue-2088 (execute, via /oversee — approved plan #2612) — feat/2088-correlated-invoked-property-evidence
carlos-alm commentedon Sep 3, 2026
execute PR opened: #2654 (feat/2088-correlated-invoked-property-evidence). Not merging — human merge only.
feat(roles): receiver-correlated invoked-property evidence for object…