Generated by
npm run eval(eval/eval.mjs) on 2026-06-19. Re-run to refresh. ComplementsRESULTS.md(token efficiency). This file answers the harder question: when agentmap returns fewer tokens, are they the right tokens?
RESULTS.md proves agentmap puts far fewer tokens in front of the agent. It does not
prove those tokens contain the correct answer — "fewer tokens" could mean "fewer correct
answers". This eval measures retrieval correctness against ground truth derived live
from real public repos, then shows accuracy and token cost together.
Ground truth is derived at runtime from each cloned repo (not hand-authored, so it can't silently rot), using a different mechanism than agentmap's parser graph — so the comparison is a real cross-check, not circular. TS/JS fixtures cross-check the ts-morph graph; the PHP/Laravel fixture cross-checks the tree-sitter-php graph (see PHP section below):
- Symbol definition — "where is symbol
Xdefined?" Ground truth = the single file whose source declaresX(regex over declaration sites). Only globally unique definitions are tested (no ambiguity). Compared:agentmap --find X(exact-name matches, in returned order) vs naivegit grep -n X(every occurrence). Metric: top-1 / top-3 hit rate (is the definition file the 1st / among the first 3 results?). - Dependents / blast radius — "which files import module
M?" Ground truth = files whose import statements resolve toM(TS: a relative-import resolver; PHP: PSR-4useresolution). Compared:agentmap --relates M.dependentsvs a naivegit grep -limport-line baseline. Metric: precision / recall / F1 against the resolved set.
Scope alignment (so the comparison is fair both ways): test files (*.test.*,
tests/, etc.) are excluded from ground truth and from both tools' outputs
before scoring — otherwise agentmap's legitimate test-file importers would score as false
positives. Type-only edges (import type / export type) are excluded from TS ground
truth, because agentmap's ts-morph graph drops them by design — counting them would penalize
recall for a documented behaviour rather than a defect. Each fixture is scoped to a
sourceRoot. Token cost = chars/4 of the full default (human) output each tool puts in
context (same heuristic as RESULTS.md, both sides).
Caveats — read these before quoting numbers. (1) The ground-truth resolvers are regex-based, not a TypeScript type-checker or PHP analyzer; they are the reference. (2) Definitions tested are uniquely-declared only — the easy, unambiguous cases. (3)
agentmap --findlists barrel re-export sites alongside the real declaration, which is why top-1 trails top-3 — the definition is usually in the top 3, not always first. (4) Dependents recall reflects agentmap's value-import graph only (type-only edges are excluded from truth to match it). (5) Feature-level retrieval (--feature) is not scored. (6) Numbers move with upstream repos; resolved SHAs are recorded below.
PHP uses a different module model than TS/JS — there are no relative-path imports. Symbols are
referenced by fully-qualified class name (FQCN), and use statements import an FQCN into a
file's namespace. So the PHP ground truth is FQCN-based, derived with a different mechanism than
agentmap's tree-sitter-php graph (keeping the cross-check honest):
- Symbol definition — regex over
class/interface/trait/enum/functiondeclaration sites (comments stripped first). Only globally-unique definitions insourceRootare tested. Compared:agentmap --find Xvsgit grep -w X. - Dependents — file B depends on file A when B has a
use A\FQCN;statement that PSR-4-resolves to A. PSR-4 prefixes are read fromcomposer.json(autoload+autoload-dev), longest-prefix-first. The grep baseline matchesuse …\ClassName;lines (the class name is the file basename — PSR-4 mandates one class per file named after it).
PHP caveats. (1) The PSR-4 resolver reads only
composer.jsonpsr-4maps —psr-0,classmap, andfilesautoloading are not resolved (rare in modern Laravel). (2) The declaration regex catches top-levelclass/functiondeclarations; dynamically-defined oreval'd classes are out of scope (and out of agentmap's scope too). (3) Dependents countsuseimports only — runtime FQCN references (\Foo\Bar::classwritten inline without ause) are not counted as edges, matching agentmap's import-graph semantics. (4) Blade views (*.blade.php) are excluded from symbol-definition ground truth — they are templates, not declaration sites. (5)laravel/frameworkis large; the eval scopes ground truth tosrc/Illuminateand samples deterministically.
| Task | n | agentmap | naive grep |
|---|---|---|---|
| Symbol definition — top-1 / top-3 hit | 100 | 63% / 96% | 41% / 81% |
| Dependents — recall / precision | 62 | 98.7% / 100% | 100% / 69.7% |
Symbol-definition lookups cost a median ~2.4× fewer tokens than dumping git grep
output, while landing the definition in the top 3 more often. For dependents the story is a
precision win, not a token win: agentmap returns a clean importer list (high precision)
where naive grep returns a noisy superset (high recall, low precision) — and --relates
actually costs more tokens than grep -l because it returns the full blast radius
(exports + imports + dependents + related), not just the file list.
| Repo | lang | commit | def n | agentmap top1/top3 | grep top1/top3 | deps n | agentmap recall/prec | grep recall/prec |
|---|---|---|---|---|---|---|---|---|
| zod | ts | 912f0f51b0 |
25 | 64% / 84% | 40% / 84% | 20 | 98.3% / 100% | 100% / 49.9% |
| zustand | ts | a1f685ca74 |
25 | 16% / 100% | 24% / 80% | 2 | 100% / 100% | 100% / 65% |
| hono | ts | 27b7992f82 |
25 | 72% / 100% | 24% / 72% | 20 | 97.5% / 100% | 100% / 66% |
| laravel-framework | php | a550e02594 |
25 | 100% / 100% | 76% / 88% | 20 | 100% / 100% | 100% / 93.7% |
npm run eval # all fixtures (TS/JS + Laravel)
node eval/eval.mjs --repo zod --sample 40
node eval/eval.mjs --repo laravel-framework # PHP/Laravel fixture standalone
node eval/eval.mjs --refresh # re-clone upstreamsClones land in tmp/eval/ (gitignored). Network required; not part of CI.