Skip to content

Native/WASM engine parity divergence + CLI -f arg-marshaling crash, affecting all open PRs' CI #2130

Description

@carlos-alm

Discovered while sweeping all 10 open PRs (#2119-#2129) on 2026-07-19/20. Every open PR showed the same "Test Node 22" / "Engine parity" CI failures regardless of what the PR actually changed — including trivial, unrelated changes like a GitHub Actions version bump (actions/setup-node, actions/setup-go, anthropics/claude-code-action) and a Gleam-only grammar bump (tree-sitter-gleam). That ruled out any of those PRs' own diffs as the cause.

Five independent sweep agents, working in isolated worktrees on unrelated PRs, each re-ran the failing jobs once and independently confirmed the exact same failure signatures reproduce deterministically — this is not occasional flakiness, it's consistently reproducible given the current main state (or very close to it). Two distinct bugs were identified:

Bug 1: Native vs WASM engine parity divergence

Both Test Node 22 and Engine parity jobs fail with real content/count mismatches between the native (Rust) and WASM engines, spanning multiple languages:

  • tests/integration/build-parity.test.ts — csharp Repository fixture:
    • "produces identical edges": native vs WASM produce 77 vs 79 edges (a real count mismatch, not just ordering)
    • "produces identical roles": UserService.UserService (a constructor) classified as role core by native but dead-ffi by WASM
    • Same test file also shows mismatches on the sample-project (JS) fixture ("produces identical nodes/roles")
  • tests/engines/ast-parity.test.tsast_nodes row-count parity:
    • typescript: WASM=2, Native=4
    • php: WASM=4, Native=6
  • tests/engines/parity.test.ts — multiple "must agree between engines" callback-gating assertions fail for JS/TS (e.g. "callback gating must agree between engines", "identifier-arg callback gating", "Array.from positional callback gating", "inline object-literal dispatch table", "identifier args to user-defined higher-order functions recognized via parameter type")
  • tests/unit/call-resolver.test.ts, tests/integration/queries.test.ts, tests/parsers/ast-nodes.test.ts also showed resolver-recall/parity assertions failing well below 100% on at least one PR's run (build(deps-dev): bump commit-and-tag-version from 12.7.3 to 13.0.0 #2123) — may be the same root cause or a related symptom; needs isolation.

Per this repo's own architecture principle ("Both engines must produce identical results. If they diverge, the less-accurate engine has a bug — fix it, don't document the gap"), this is a real bug in whichever engine is wrong, not acceptable drift.

Investigation lead (unconfirmed): commit 156004ac / PR #2102 ("fix(extractors): extract bare super(...) constructor calls as call edges", merged 2026-07-17) touches extractor logic and directly involves constructor-call edges — plausible mechanism for the C# constructor-role divergence above. However, main's own official push-triggered CI run for that exact commit (2e0e94fa) passed Engine parity cleanly on all 3 platforms, while multiple PR-triggered runs against the same or near-identical commit fail consistently. That discrepancy (push-run passes, PR-runs fail) is itself worth investigating — possibly a pull_request vs push event/matrix/concurrency difference, test ordering sensitivity, or environment/caching difference between trigger types — rather than assuming the extractor change itself is deterministic-safe.

Bug 2: Native addon crash on CLI -f array arguments

A separate, also deterministically-reproducing failure:

codegraph: fatal error — Failed to convert JavaScript value Object ["math.js"] into rust type String

Confirmed identical on multiple independent PR runs. Affects:

  • tests/cli.test.ts (-f scoping tests)
  • tests/integration/incremental-parity.test.ts
  • Multiple regression tests: issue-1730, issue-1734, issue-1738, issue-1742, issue-1753, issue-1769

This looks like a native (napi-rs) binding issue marshaling an array argument (-f/file-filter) as a single string, rejecting an array/object where a Rust String is expected.

Evidence this is deterministic, not flaky

Reproduced with the identical failure signature (same test names, same fixtures, same counts) across at least 5 separate CI runs triggered by completely unrelated PRs:

None of these PRs touch extraction, parsing, or native-binding code, so their diffs cannot be the cause.

Impact

Every open PR in this repo currently shows red CI on Test Node 22 and Engine parity regardless of content, which:

  • Makes CI red the default/expected state, eroding its value as a merge gate
  • Blocks the dual-engine parity guarantee this project's architecture depends on
  • Forces every PR author/reviewer to manually distinguish "real failure" from "known noise"

Suggested next steps

  1. Bisect between the last known-good push-triggered main run and the first PR run showing this signature to find the actual introducing commit (candidate: fix(extractors): extract bare super(...) constructor calls as call edges #2102, but not confirmed).
  2. Reproduce locally (not just in CI) to rule out CI-environment-specific causes (concurrency, caching, pull_request vs push trigger differences).
  3. Fix the identified engine's incorrect output for Bug 1 (per project policy: fix the less-accurate engine, don't special-case the test).
  4. Fix the napi-rs argument marshaling for Bug 2's -f flag handling.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions