Repository navigation
#1790 drops every identifier-rooted member call, not just built-in collections — 8 tests red on main #1794
Description
de5adba (#1790) makes codegraph_explore, callers, impact and Steps lose the callee of any
a.b.c() call whose chain is rooted at a project identifier. Eight of this repo's own tests fail on
main because of it.
Bisect
Same worktree, same bun install, __tests__/{ui-steps-cross-tier,ui-steps-api-servers,nextjs,react-native-bridge}.test.ts:
| commit | result | |
|---|---|---|
2f8cce5 |
base | 90 passed |
7be699c |
#1785 | 90 passed |
b8d46d1 |
#1788 | 90 passed |
72c1ff1 |
#1789 | 90 passed |
de5adba |
#1790 | 8 failed, 82 passed |
de5adba re-run back-to-back after its parent in the same checkout, so this is not install state.
Node v24.16.0, Windows 11, vitest run.
Failing tests
nextjs.test.ts > nextjs: end to end > a page's Steps picture fires from its load, crosses to the server action, and draws the pages it leads to as boundaries
nextjs.test.ts > nextjs: end to end > an endpoint anchors as any server route does
react-native-bridge.test.ts > React Native cross-platform pairing — end to end > links the Android (@ReactMethod) and iOS (RCT_EXPORT_METHOD) impls of a JS-called method
ui-steps-api-servers.test.ts > in the code's order > reads an Express handler as it is written, helper and all
ui-steps-api-servers.test.ts > Express > draws the handler's database write, the queue job, the email, and the 201 — after the middleware
ui-steps-api-servers.test.ts > Express > walks an inline handler as the route itself, into the service's read and its 404
ui-steps-cross-tier.test.ts > the Steps picture across the tiers > draws the route as a boundary the form crosses to (⇢), and enters it on request
ui-steps-cross-tier.test.ts > the Steps picture across the tiers > a server action called from a client component is a crossing to the server, by its directive
Representative assertion — ui-steps-cross-tier.test.ts:461:
expect(effect(p, 'database')?.effect?.by.name).toBe('createUserAction')
AssertionError: expected undefined to be 'createUserAction'
Cause
src/extraction/tree-sitter.ts replaces tsJsChainRoot with isUnresolvedTsJsChain:
function isUnresolvedTsJsChain(node: SyntaxNode, source: string): boolean {
let cur: SyntaxNode | null = node;
while (cur && TS_JS_CHAIN_RECEIVER_TYPES.has(cur.type)) {
cur = getChildByField(cur, 'object');
}
return !!cur && cur.type === 'identifier' && getNodeText(cur, source) !== 'window';
}The old gate suppressed a member call only when the chain was rooted in TS_JS_HOST_GLOBAL_ROOTS
(chrome, document, Math, …). The new one suppresses every identifier-rooted chain except
window. db.users.insert(x), queue.add(job), mailer.send(msg) and res.status(201) now emit
no call at all, so Steps effects have no by and cross-tier boundaries are not drawn.
The comment #1790 removed had recorded the opposite judgement for exactly this case:
A chain rooted at a project value (
window.MyNs.run(),store.getState().act(),ref.value.m())
keeps the bare name — those targets are real, and dropping them would cost far more recall than
the mis-bind costs precision.
#1566 wants holder.values.get() unresolved because the property type is unknown. That is a subset
of what the predicate now matches: a chain is being treated as untyped whenever it is
identifier-rooted, which is the common case for project objects, not the exception.
Repro
git checkout de5adba
bun install --frozen-lockfile
node node_modules/vitest/vitest.mjs run __tests__/ui-steps-cross-tier.test.ts \
__tests__/ui-steps-api-servers.test.ts __tests__/nextjs.test.ts \
__tests__/react-native-bridge.test.ts
Reverting de5adba restores 90/90 on those four files, and ts-chained-receiver.test.ts plus
resolution.test.ts stay green at 296/296 with #1792 (cece072) also applied.
Not proposed as the fix — narrowing the predicate back toward the #1566 case (an inferred-collection
receiver) rather than all identifier roots looks like the direction, but I have not measured which
narrowing keeps #1566 green without costing the recall above.
Activity
inth3shadows commentedon Sep 9, 2026
Reproduced on Linux, and the full suite turns up one more test with this cause than the four files above cover.
__tests__/mcp-callers-truncation.test.ts > codegraph_callers truncation > marks the cut inside each per-definition section too— not in the list above, same bisect result:72c1ff13ed73bcHow this was arrived at
Not a targeted run — it fell out of baselining an unrelated branch. I ran the full suite (
npm test, 273 files) on a merge of currentmain, got 13 failures, then re-ran the same 8 files on cleanupstream/mainto check whether my merge caused them. Identical set, so all 13 are main's. Bisecting those 13 against72c1ff1and2f8cce5splits them three ways:de5adba(fix: prevent built-in Map calls from resolving to project methods (#1566) #1790) — the 8 above (green-at-parent per your table; I confirmed only that all 8 fail here at3ed73bc, I did not re-bisect them), plusmcp-callers-truncation, which I did bisect: green at72c1ff1, red at3ed73bc.object-literal-methods(expected [] to include 'loginFlow') andui-steps-api×2 (expected undefined to be 'store',Cannot read properties of undefined (reading 'region')). These fail at72c1ff1and at2f8cce5, so they predate fix: prevent built-in Map calls from resolving to project methods (#1566) #1790 entirely. Already diagnosed — PR fix(resolution): a same-name re-binding is not a local definition #1760 names these same tests.ui-server-api > the engine's own busiest symbolassertselapsed < 100; it measured143.14here. A wall-clock budget, machine-dependent, unrelated to either cause.The
2f8cce5row above is worth noting against the bisect table in the opening comment: it is listed there as a green base at 90 passed, which it is for those four files — but three other files already fail at it, from #1759. Worth separating so #1790's fix isn't judged against a suite that stays red for a different reason.Environment: Linux 6.6 (WSL2),
vitest run, on both Node v22.23.2 (inside this repo'senginesrange) and v26.7.0 (outside it). The two are identical — 13 failed / 163 passed each, same 13 names, diffing byte-for-byte. The runtime is not a factor anywhere in this, the perf assertion included:138.11on v22 and143.14on v26 against its< 100budget, so that one is a slow machine rather than a Node version.Flagging the platform because #1773 makes the point that the Windows counts track machine load — these are not timeouts, they are assertion failures on missing graph edges, and they reproduce off Windows on a supported Node.
Edited to attribute the green-at-parent row for the 8 to your table rather than to a run of my own, and to add the v22 numbers — the original said only v26 and asked readers to discount the counts for it, which is no longer necessary.
@danusha2345's correction below supersedes my third bullet: the
hardReset → resetassertion is #1790's class, not #1759's, so the split is 10 / 2 / 1, not 9 / 3 / 1.danusha2345 commentedon Sep 9, 2026
Confirming the three-way split on Linux against
3ed73bc. With #1760 merged onto currentmain(head2b126b6, no conflicts):ui-steps-api×2 and theloginFlow → fetchUserhalf ofobject-literal-methodspass. The remaining failure in that same test is the other assertion,hardReset → resetviauseStore.getState().reset()— an identifier-rooteda.b().c()chain, i.e. the #1790 class you bisected, not #1759. So #1760 clears the #1759 group and leaves the #1790 group untouched.bompus commentedon Sep 11, 2026
Thanks both — the 10 / 2 / 1 split matches what I see. #1844 is the fix for the #1790 group: it keeps the full nested receiver text so the call-site evidence Steps and the framework resolvers need survives, while generic import and last-name matching still refuse to bind an imported root or an unrelated
get. It bumps the extraction version, so existing indexes need a rebuild after it lands. ThehardReset → resetassertion viauseStore.getState().reset()is in that PR's test set.docs(design): kernel-only extraction, resolution binding model, green…
danusha2345 commentedon Sep 15, 2026
Rechecked on main@58c07e8 (after #1862 and #1849):
object-literal-methods(bothloginFlow → fetchUserandhardReset → reset),ui-steps-api,mcp-callers-truncationandrelease-main-regressionsall pass on Linux (WASM arm). Closed #1760 as superseded by #1862. From my side this issue looks resolved on main.test(resolution): keep compound receiver evidence without guessing ta…
colbymchenry commentedon Sep 27, 2026
Thanks for the detailed report, @bompus, and thanks for using CodeGraph! This is fixed on
mainby the regression-audit merge (f1ea898): identifier-rooted member calls keep their call evidence again, and the tests this broke are green. The fix will be in the next release.test(resolution): calls on nested receivers keep their evidence and g…