Repository navigation
Description
Problem / Goal
The import graph resolves 8 language families (JS/TS, Python, Go, Rust, JVM, Ruby, Elixir, R) of the 38 SigMap extracts, so file-level impact, plan's blast radius and the graph boost are blind for the rest (measured in the guard issue: 0 edges on PHP, C#, Dart, Swift, Lua, GDScript and C++ clones). codebase-memory-mcp and code-review-graph both resolve these (Tree-sitter, per their READMEs). This is the largest single contributor to the "code graph" gap that does not need Tree-sitter: most of these import forms are explicit, regular and cheap to resolve deterministically.
Proposed solution
One resolver per language family inside src/graph/builder.js's existing pattern (extractFileDeps plus a per-build lookup table), zero dependencies, in value order:
- C / C++ / Objective-C:
#include "x.h"/#import "x.h", resolved relative to the file, then the include roots. Angle-bracket system headers ignored. - PHP:
use Ns\Class;plusrequire/includewith literal paths, resolved throughcomposer.jsonautoload.psr-4. - C#:
using Ns;resolved through an index ofnamespace Xdeclarations built in the same pass. - Dart:
import 'package:pkg/x.dart'(local package) and relative imports. - Vue / Svelte / Astro single-file components: parse the
<script>/ frontmatter block and reuse the JS/TS resolver. These file types are not inJS_EXTStoday, so a.vuefile contributes no edges even though its script imports are ordinary ES imports. - Lua
require("a.b")toa/b.lua; GDScriptpreload("res://x.gd")/load(...). - Swift: module-level only (a file depends on the target that declares an imported module); no file-level edges are invented.
For each: precision first. An unresolvable import produces no edge (as the JS resolver does for bare package names), never a guessed one.
Measure with the references already planned, not by eye: SCIP-derived edges (#976) where an indexer exists, plus a git co-change reference for file-level impact (files changed together in a commit, independent of the graph), on the clones listed above.
Impact
Moves the graph from 8 to roughly 15 language families, makes --impact, plan and get_impact meaningful on PHP, C#, C/C++, Dart and the frontend frameworks, and gives the ranker's graph boost something to work with on exactly the repos where retrieval is weakest (laravel 40%, serilog 40%, riverpod 60%). Whether the boost helps retrieval there is an open question: #935 found no damping rule worth shipping on the current graphs, so retrieval is a measured side effect, not a promise.
Acceptance criteria
- A resolver and fixtures per language above (fixtures include re-exports, aliases, conditional includes, and unresolvable imports that must yield no edge).
- Edge precision and recall against the chosen references published per language (shares the harness of benchmark: call-graph accuracy against a compiler-derived reference (SCIP) - no one publishes a non-circular number #976).
- The Laravel
Str.phpcase reports its importers (about 164). - xrepo per-repo no-regress holds; any movement on laravel / serilog / riverpod is reported unedited, win or lose.
-
KNOWN_LIMITATIONS.mdgraph language list updated.
Related: #976, #935, #934, the graph guard issue (do that first).
Pickup (epic #978)
- Order: 11
- Wave: W4
- Size (rough guess for one maintainer): L
- Blocked by: graph: --impact and get_impact say 'no importers' for PHP, C#, Dart, Swift, Lua, GDScript and C/C++ - the import graph reads 8 of 38 languages #979, benchmark: call-graph accuracy against a compiler-derived reference (SCIP) - no one publishes a non-circular number #976
- Unblocks: -
- Moves (scorecard): Graph 5 to 7
- Close with an evidence block (command, before, after, environment, report, the test that fails on the old code); see "Closing rule" in epic: close the gap - 2026-10-17 gap analysis (scorecard 59.8/100 vs codebase-memory-mcp 83.2, code-review-graph 66.9) #978.
Activity
fix(graph): find a Dart package's pubspec.yaml by the directory's rea…
fix(benchmark): let the Swift reference write to a file, not /dev/std…
manojmallick commentedon Oct 26, 2026
Evidence for #980, from PR #1030 (not merged, not released).
Command
Nine pinned repositories (the commits the xrepo manifest pins), each exported with
git archiveinto a scratch directory; the shared clones are only read. Protocol and eight predictions committed in975d281, before the scorer ran on any evaluation repository;--saverefuses a partial run, an edited protocol and a dirty scored tree.Before
The import graph read eight families. For a PHP, C/C++, C#, Dart, Vue, Svelte, Astro, Lua or GDScript file it drew no edge (
--impactsaidgraph: unsupported-language, #979), and for Swift likewise. No edge, so nothing to measure, and no accuracy figure for any language.After (registered run, scorer at
7287d5a, protocol sha256e259922692bf…)clang -E -H, 3 configurations): libuv, abseil-cppswiftc+ SwiftPM): alamofire, vaports.resolveModuleName): vue-core, svelte, astroRegistered predictions: P1, P2, P3, P5, P6, P7, P8 held; P4 (component recall ≥ 90%) missed at 79.1%. 390 of the 406 component misses are in svelte (389: files inside the
sveltepackage importing"svelte", resolved by TypeScript through the package's ownexports); the rest are./x.jswritten forx.ts(12), JSON modules (3), a#nameimport (1) and one pair of files whose names differ only in case (the run was on a case-insensitive filesystem). All live in the resolver every.js/.tsfile shares; not changed here (it also builds the ranker's graph, #934).C#, Dart, Lua, GDScript: resolvers and fixtures with known answers, no figure (no reference could be run; reasons in the protocol).
Other acceptance criteria:
Str.php: 167 direct importers, every PHP source file that namesIlluminate\Support\Str; the four othergrephits are Blade templates.develop.KNOWN_LIMITATIONS.md: graph language list (fifteen families), what each resolver counts, the measured figures, the gaps.Deviation log (in the protocol): three runs. The second reproduced the first exactly and added a why-was-it-missed breakdown; reading the misses showed two defects in the new component reader (a blank line before an Astro
---fence; a recursive component importing itself), fixed in91aec34; the third run is the saved report. C, PHP, Swift are bit-for-bit the same across all three.Environment: macOS (Darwin 25.5.0) arm64, load average about 4 on a shared machine; Node v25.6.0; Apple clang 21.0.0; Apple Swift 6.3.2; PHP 8.4.23 and Composer 2.10.3 (sha256-checked);
typescript6.0.3,@vue/compiler-sfc3.5.44,svelte5.57.2,@astrojs/compiler4.0.0.Report:
benchmarks/reports/import-accuracy.json; methodbenchmarks/IMPORT_RESOLVER_PROTOCOL.md; pagedocs-vp/guide/import-accuracy.md(tables generated from the report and pinned to it by a test).Regression tests:
test/integration/import-resolvers.test.js(29; 50/50 mutants killed),test/integration/import-accuracy.test.js(22 with the reference tools; 32/32 mutants killed),test/integration/graph-unsupported-languages.test.js(35). Full integration suite 261 passed, 0 failed.Found, not fixed (needs your call): the JS/TS import matcher is line-based, so an import list that spans several lines (
import {\n a,\n b\n} from './x') gives no edge in a plain.ts/.jsfile. Components are read; plain JS/TS is not, because the ranker's graph is built from the same matcher.Merge pull request #1030 from manojmallick/feat/import-resolvers-980