Skip to content

Import-graph accuracy ​

--impact, get_impact, the blast radius in plan and the counts in sigmap doctor answer from SigMap's import graph (src/graph/builder.js). Until #980 it read eight language families; it now reads fifteen (C/C++/Objective-C, PHP, C#, Dart, Vue/Svelte/Astro, Lua and GDScript were added) and gives a module-level answer for Swift. This page measures how far the edges it draws agree with what each language's own tooling resolves.

The reference is never SigMap's own resolver. It is the compiler or the framework's parser: clang -E -H for C and C++, TypeScript's module resolution behind the Vue, Svelte and Astro parsers for components, PHP's tokenizer and Composer's autoloader for PHP, and the Swift compiler with SwiftPM for Swift. Call it compiler-derived, not ground truth: a reference reports the configuration it ran, and an import that depends on another configuration is not in it.

The method, the repositories, the predictions and the thresholds were written down and committed before the scorer ran on any of them (benchmarks/IMPORT_RESOLVER_PROTOCOL.md). The deviation log in that file records everything that happened after the first run, with the first run's figures kept. The full numbers, and the first disagreements of every repository, are in benchmarks/reports/import-accuracy.json.

Results ​

Measured on SigMap 8.82.0 (commit 7287d5a), protocol 975d281; Node v25.6.0 on darwin-arm64. References: Apple clang version 21.0.0 (clang-2100.1.1.101); typescript 6.0.3, @vue/compiler-sfc 3.5.44, svelte 5.57.2, @astrojs/compiler 4.0.0; PHP 8.4.23, Composer 2.10.3; Apple Swift version 6.3.2 (swiftlang-6.3.2.1.108 clang-2100.1.1.101).

Headline ​

Precision and recall are over edges whose importing file both the graph and the reference read. Brackets are 95% cluster-bootstrap intervals over importing files; a cell with fewer than 100 edges is not quoted.

GroupRepositoriesReference edgesRecallGraph edgesPrecisionF1
C / C++ / Objective-Clibuv, abseil-cpp4,61199.7% (99-100)4,60999.7% (99-100)99.7%
Vue / Svelte / Astrovue-core, svelte, astro1,94179.1% (77-81)1,535100.0% (100-100)88.3%
PHPlaravel, composer4,975100.0% (100-100)4,976100.0% (100-100)100.0%
Swift (module level)alamofire, vapor15199.3% (98-100)150100.0% (100-100)99.7%

By repository ​

GroupRepositoryCommitImporting files scoredReference edgesGraph edgesPrecisionRecall
C / C++ / Objective-Clibuv20b083433067768399.1%100.0%
C / C++ / Objective-Cabseil-cppea64b6e8603,9343,92699.8%99.6%
Vue / Svelte / Astrovue-core7df0edd111414100.0%100.0%
Vue / Svelte / Astrosvelte4a50e8e4,2381,316926100.0%70.4%
Vue / Svelte / Astroastro4c1470a1,098611595100.0%97.4%
PHPlaravel635129b1,6193,6253,625100.0%100.0%
PHPcomposer28145ca3141,3501,35199.9%100.0%
Swift (module level)alamofire903c53c984343100.0%100.0%
Swift (module level)vaporcfd8f43294108107100.0%99.1%

Scope ​

GroupRepositoryFiles the graph walkedFiles the reference could analyseScored (both)Graph edges outsideReference edges outside
C / C++ / Objective-Clibuv33033033000
C / C++ / Objective-Cabseil-cpp86086086000
Vue / Svelte / Astrovue-core11111100
Vue / Svelte / Astrosvelte4,3394,2384,23800
Vue / Svelte / Astroastro1,1011,0981,09800
PHPlaravel1,6191,6191,61900
PHPcomposer31431431400
Swift (module level)alamofire98989800
Swift (module level)vapor29429429400

Why edges were missed ​

Reference edges the graph lacks, by how the import reaches its fileC / C++ / Objective-CVue / Svelte / AstroPHPSwift (module level)
a bare specifier that resolves inside the repository038900
reaches a .inc file16000
written .js/.jsx, the file is .ts/.tsx01200
a JSON module0300
a "#name" import of the package.json imports map0100
a module with no Swift file (a C-language target)0001
a relative path0100
all1640601

Where the missed edges are ​

GroupRepositoryHow the missed import reaches its fileReference edges missed
C / C++ / Objective-Cabseil-cppreaches a .inc file16
Vue / Svelte / Astrosveltea bare specifier that resolves inside the repository389
Vue / Svelte / Astrosveltea relative path1
Vue / Svelte / Astroastrowritten .js/.jsx, the file is .ts/.tsx12
Vue / Svelte / Astroastroa JSON module3
Vue / Svelte / Astroastroa "#name" import of the package.json imports map1
Swift (module level)vapora module with no Swift file (a C-language target)1

Graph edges the reference does not have ​

Graph edges the reference lacks, by what they reachC / C++ / Objective-CVue / Svelte / AstroPHPSwift (module level)
reaches a .h file14000
reaches a .php file0010
all14010

Not measured ​

WhatKindWhy there is no figure
C#languageno compiler-grade reference was run
Dartlanguageno compiler-grade reference was run
Lualanguageno reference exists to run
GDScriptlanguageno reference exists to run

The registered predictions ​

Registered predictionResultMeasured
P1C/C++ recall is at least 90%: the resolver searches the way the compiler does, and the compiler's include dirs are the ones registeredheld99.7%
P2C/C++ precision is at least 80%: a platform branch the three configurations do not enable is an include the graph counts and the reference does notheld99.7%
P3component precision is at least 95%: a specifier either resolves to a file TypeScript also resolves it to, or not at allheld100.0%
P4component recall is at least 90%; the misses are the bundler aliases and .js-to-.ts mappings the JS resolver does not readmissed79.1%
P5PHP precision is at least 95%held100.0%
P6PHP recall is at least 85%held100.0%
P7Swift module-level precision is at least 99%held100.0%
P8Swift module-level recall is at least 99%held99.3%

How to read them ​

Precision is the share of the graph's edges that the reference also has. Recall is the share of the reference's edges that the graph has. Both are over the importing files that the graph walked and the reference could analyse, so a file the reference could not parse is out of both counts and shows in the scope table as walked but not scored (svelte's deliberately invalid compiler-error samples are of this kind). The graph's walk is the zero-config one a user gets.

C, C++ and Objective-C. The two agree on almost every include. The extra edges are includes behind a platform switch (unix.h including aix.h, os390.h, sunos.h): the reference ran the host, Linux and Windows, and an include behind another switch is not in it, so the precision is a lower bound. The missed edges are all .inc files, which the graph does not treat as source files (abseil uses them for per-platform fragments).

PHP. The two agree on every use of a class in laravel and composer. The one extra edge is a literal require of a file, which the reference does not read, so PHP precision is also a lower bound.

Swift is module level. A Swift file imports a module, not a file, so the graph draws no file-to-file edge for Swift and the reference edge is "this file imports that target of the package". --impact on a Swift file names its target and lists the files in other targets that import it. The one miss is a C-language target of vapor, which has no Swift file to ask about.

Components, and the prediction that was missed. Every edge the graph draws between components is one the reference has (precision above), but component recall is the lowest of the four groups. The registered prediction was 90% recall; it was missed. None of the remaining causes is in the component reader (two defects there were found by this benchmark and fixed, and are in the deviation log): the script found in a .vue, .svelte or .astro file goes through the same specifier resolution as a .ts file, and that resolver does not read

  • the package's own name, resolved through the exports field of its own package.json (every file of the svelte package that imports svelte reaches types/index.d.ts; all of the "bare specifier" misses are in that one repository);
  • a specifier written ./x.js for a file x.ts, or ./x.jsx for x.tsx, which is how TypeScript projects write imports under Node's rules;
  • a JSON module, and a #name import of the imports map;
  • an extension-less specifier that reaches a .d.ts file.

The registered guess named bundler aliases and .js-to-.ts mappings; the second is real (a dozen edges, all in astro), but the larger cause is the package naming itself, in svelte. These are real gaps for every .js and .ts file too, which this benchmark does not measure. They are not fixed here: that resolver also builds the graph the ranker reads, so widening it moves retrieval (#934) and needs its own review against the retrieval gate. A list of imports that spans several lines is read in a component's script and, for the same reason, is not read in a plain .js or .ts file.

Not measured. C#, Dart, Lua and GDScript have resolvers and test fixtures with known answers, but no figure. A C# or Dart reference is a compiler front end that needs an SDK, a restore and a build of the repository; Lua finds a module through a path the project sets at run time; and GDScript is resolved by the engine. A number from a weaker oracle would be a number about the oracle, so there is none.

What the figures do and do not say ​

  • They say how often the graph's edges agree with what each language's tooling resolves, for these repositories, over the files both read. They are not a statement about every repository, and a repository's own build configuration (a -D switch, a bundler alias table) can change what its tooling resolves.
  • A cell with fewer than 100 edges is shown and not quoted; the intervals are 95% cluster-bootstrap intervals over importing files.
  • Precision says nothing about completeness and recall says nothing about the extra edges; read the two together, and read each against the reference's own limits above.
  • The ranker's neighbour boost still reads only the original eight families. These figures are about the blast-radius surfaces, not about retrieval.

Reproduce ​

bash
node scripts/fetch-xrepo-repos.mjs --only libuv,abseil-cpp,vue-core,svelte,astro,laravel,composer,alamofire,vapor
node scripts/run-import-accuracy.mjs --setup-references /path/to/refs     # pinned TypeScript, the framework parsers, PHP and Composer
node scripts/run-import-accuracy.mjs --references /path/to/refs            # prints the tables
node scripts/run-import-accuracy.mjs --references /path/to/refs --save    # also writes benchmarks/reports/import-accuracy.json
node scripts/run-import-accuracy.mjs --write-doc                          # re-renders the tables above from the saved report

C and Swift need clang and swift on the path. Each repository is exported at its pinned commit into a scratch directory, so the shared clones are only read. --save refuses a partial run, a protocol that differs from the committed one, and a scored tree with uncommitted changes.

MIT License