fix(js): extract methods assigned to factory object APIs - #2745
fix(js): extract methods assigned to factory object APIs#2745rajanpanth wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Graphify reviewed this change.
Looks safe to merge — no coupling regressions and no blocking issues, checked against the code graph (not a self-assessment).
Formal verification. No changes could be formally verified in this run.
Graphify review — findings
This PR extends the JavaScript/TypeScript extractor in graphify/extractors/engine.py to capture callable members assigned to local object-literal variables inside a function body (e.g. factory patterns like const api = {}; api.foo = fn), in addition to the existing this.X = fn handling. The _js_member_assignment_target helper now returns an ("object", name, member) tuple for arbitrary identifier receivers instead of returning None, and the caller in _extract_generic collects object-literal bindings and materializes owner nodes/edges only for those tracked identifiers. A new test, test_extract_js_factory_object_assigned_methods, is added to exercise this factory-object scenario and assert the expected node labels and contains/method/calls edges. The large set of other changed test symbols appears to reflect incidental renumbering/shifts in the test module. The surface area is the JS/TS member-assignment extraction path and the associated test file.
No blocking issues surfaced. 3 lower-confidence candidates did not survive cross-model review.
Analysis details — impact, health, verification
Impact & health
Graphify review
Impact — 897 functions depend on the 534 functions this change touches.
Health — this change adds coupling hotspots:
- worse:
extract_js()— 77 callers, 3 callees
Verification — 897 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: 838 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 \_js\_member\_assignment\_target.
The verifier did not have enough to check \_js\_member\_assignment\_target, 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: not verifiable: all 182 sampled inputs raised on both versions — the function never executed, so 'no divergence' would be vacuous (mostly AttributeError — names the real obstacle, not a sampling gap)
· 1 more finding(s) on lines outside this diff (see the check run).
Preserve callable members assigned to a local object-literal factory API
(`const api = {}; api.foo = fn`), modeling the API object beneath its factory
and attaching the assigned functions as methods. The lazy owner-node minting
(only for identifiers proven to be object-literal bindings in the enclosing
function) avoids the #1077 config-object flood.
Partially addresses #2524 (the object-literal-method shorthand form
`return { foo() {} }` remains out of scope).
…ver (#2745) The factory-object owner path emitted the `contains` edge inside the per-member loop; add_node dedups on id but add_edge does not, so N methods assigned to one object flooded the graph with N identical contains edges. Emit it once per owner. Tests: assert a single contains edge across four methods, cover arrow-function assignment (the dominant modern factory shape), and lock the negative case that a non-object-literal receiver (`external.handler = fn`) is not captured.
Ships this cycle: the graph-correctness/UX batch — JS/TS factory-object methods (#2745), stable graph.json field order (#2582), query names its graph (#2789), ThinkingBlock-safe claude backend (#2697), manifest churn guard (#2838), C# primary ctor refs (#2829), AST INFERRED rubric confidence_score (#2813), legacy numeric confidence normalization; plus the small-fix batch — chunk-bisect on timeout (#2866), symlink cache identity (#2832), sidecar cache root (#2787), driveless Windows path guard (#2795), actionable partial-parse warning (#2788), and non-ASCII Obsidian tags (#2862). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Shipped in v0.9.47 via authorship-preserving cherry-pick. On the way in I deduped the factory contains edge (it was being emitted once per method) and added arrow-assignment and bare-receiver tests. This fully resolves #2524. Thanks @rajanpanth! Release: https://github.com/Graphify-Labs/graphify/releases/tag/v0.9.47 |
Summary
Verification
uv run pytest tests/test_extract.py -quv run ruff check graphify/extractors/engine.py tests/test_extract.pyuv run graphify update .Fixes #2524