Repository navigation
Reproducible niche prior-art benchmark (Codebase Context vs jCodeMunch, Aider, Repomix, ripgrep) - #156
Reproducible niche prior-art benchmark (Codebase Context vs jCodeMunch, Aider, Repomix, ripgrep)#156PatrickSys wants to merge 2 commits into
Conversation
Extend the existing eval fixtures with a frozen 18-task manifest across three public repos, a one-command runner comparing Codebase Context to jCodeMunch, Aider repo map, Repomix, and ripgrep, and checked-in evidence plus benchmark.md reporting including known losses.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 453d2712ec
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const columns = line.split(','); | ||
| const fileColumn = columns[3] ?? columns[4]; | ||
| const normalized = normalizeRelativePath(fileColumn ?? ''); |
There was a problem hiding this comment.
Extract file paths rather than symbol kinds from compact results
For the compact jCodeMunch responses used by this run, this column selection extracts symbol kinds instead of file paths. The checked-in evidence confirms that jCodeMunch's topFiles contain values such as method, function, and type throughout all 18 tasks. Consequently, actual retrieved files cannot score hits, while type incorrectly satisfies the expected type substring for ex-sym-01. Parse the compact response's actual file field and regenerate the evidence and comparison table before publishing the 5.6% result.
Useful? React with 👍 / 👎.
| ['--yes', 'repomix', '--stdout', '--quiet', '--style', 'plain'], | ||
| { cwd: repoPath, timeoutMs: 900_000 } |
There was a problem hiding this comment.
Exclude generated benchmark indexes from the Repomix corpus
In the default lane order, Codebase Context creates .codebase-context indexes before Repomix packs each checkout, but this pack invocation does not exclude those generated artifacts. The checked-in evidence shows that every Repomix task returns only .codebase-context/.generations/.../index/index-build.json, rather than a source file from the pinned repository. This also creates false hits for Excalidraw queries accepting json, and charges the generated indexes to Repomix's token cost. Exclude benchmark-generated directories from the comparator corpus and regenerate the results.
Useful? React with 👍 / 👎.
| const manifest = loadJson(manifestPath); | ||
| const protocol = loadJson(protocolPath); | ||
| const errors = []; | ||
| if (manifest.tasks.length !== 18) errors.push(`expected 18 tasks, found ${manifest.tasks.length}`); |
There was a problem hiding this comment.
Meet the required minimum evaluation-set size
The runner explicitly rejects any task count other than 18, and the new fixture test enforces the same count. Root AGENTS.md requires at least 20 queries for an evaluation set and explicitly makes evaluation-integrity violations a shipping blocker. Expand the benchmark to meet that minimum and update validation and tests before regenerating the published results; the current validator instead locks in the noncompliant size.
AGENTS.md reference: AGENTS.md:L138-L143
Useful? React with 👍 / 👎.
| "description": "Frozen 18-task niche benchmark across three public repos, two tasks per niche per repo. Expected patterns are path substring checks, not full paths.", | ||
| "frozenDate": "2026-10-30", |
There was a problem hiding this comment.
Establish a committed fixture baseline before implementation
This fixture first appears in the same commit as the benchmark implementation and completed evidence; it is absent from the parent commit. A frozenDate field therefore does not establish the independently committed preimplementation baseline required by root AGENTS.md. Establish that baseline for the next benchmark iteration before implementation and measurement, and do not describe the current results as satisfying the repository's frozen-fixture requirement.
AGENTS.md reference: AGENTS.md:L131-L135
Useful? React with 👍 / 👎.
| } from './lib/niche-benchmark/lanes.mjs'; | ||
| import { aggregateEvidence, aggregateLaneResults } from './lib/niche-benchmark/scoring.mjs'; |
There was a problem hiding this comment.
Put the evaluation implementation under tests
The full benchmark implementation is introduced under scripts/, including the runner, lane adapters, scorer, and Python helper; tests/ contains only fixtures and a small test importing that implementation. Root AGENTS.md explicitly requires the full evaluation harness code to live in tests/. Move the implementation there and retain a thin npm entry point if needed so this benchmark meets the repository's public-evaluation layout requirement.
AGENTS.md reference: AGENTS.md:L145-L150
Useful? React with 👍 / 👎.
[Low impact] The changes affect a local benchmark workflow and its report. Do not merge the published comparison until file parsing and shared-checkout contamination are fixed and the repository's evaluation requirements are met. Findings
SummaryAdds an 18-task benchmark across three pinned repositories, with five tool lanes, scoring tests, saved evidence, and rerun instructions.
Diagram%%{init: {'theme': 'neutral'}}%%
flowchart LR
A[Frozen tasks and protocol] --> B[Pinned repository checkouts]
B --> C[Warm each tool]
C --> D[Run task queries]
D --> E[Extract ranked file paths]
E --> F[Score hits and costs]
F --> G[Aggregate saved evidence]
G --> H[Benchmark report]
Reviews (1) · Last reviewed commit: "Ignore Aider tag cache created by repo-m..." · Reviewed by Greptile |
| const columns = line.split(','); | ||
| const fileColumn = columns[3] ?? columns[4]; | ||
| const normalized = normalizeRelativePath(fileColumn ?? ''); |
There was a problem hiding this comment.
The compact jCodeMunch parser reads symbol kinds instead of file paths. The saved ex-sym-01 result has topFiles: ["type"] and earns a hit because "type" matches an expected pattern. Other tasks contain "method" or "constant". This makes the published accuracy score invalid. Parse the actual file column, add a compact-response fixture, and regenerate the results.
| for (const laneId of lanes) { | ||
| console.log(`\n=== Lane: ${laneId} ===`); | ||
| try { | ||
| laneEvidence[laneId] = await runLane(laneId, manifest, repoCheckouts); |
There was a problem hiding this comment.
Lanes search each other's files
Every lane reuses the checkout after Codebase Context writes its index there. Neither ripgrep nor Repomix excludes .codebase-context, and the saved results show both returning those generated files. Their scores and token counts therefore measure more than the pinned repository and depend on earlier lanes. Use separate clean checkouts, or consistently exclude every lane's generated files, then regenerate the evidence.
Knowledge Base Used: Evaluation and ContextBench
| if (index.status !== 0) { | ||
| return { | ||
| status: 'setup_failed', | ||
| reason: `codebase-context reindex failed on ${group.repo.id}`, | ||
| taskResults: [] | ||
| }; |
There was a problem hiding this comment.
Late failures erase completed results
If setup fails on a later repository, this return discards rows already collected from earlier repositories. A thrown query error also reaches the outer catch and clears the whole lane. Keep completed rows and record failed or unrun tasks separately so the saved evidence still shows what finished.
| const started = Date.now(); | ||
| const result = runCommand( | ||
| process.platform === 'win32' ? 'npx.cmd' : 'npx', | ||
| ['--yes', 'repomix', '--stdout', '--quiet', '--style', 'plain'], |
There was a problem hiding this comment.
Comparator versions are not frozen
The rerun uses unversioned Repomix, and the Python prerequisites have no recorded versions either. The evidence records Node's version but not the comparator versions. Pin these tools and save their versions with each run so users can recreate the behavior behind this frozen comparison.
| "id": "jCodeMunch", | ||
| "displayName": "jCodeMunch", | ||
| "credit": "jCodeMunch MCP symbol search and repo indexing (jcodemunch-mcp on PyPI).", | ||
| "projectUrl": "https://github.com/jgrahamc/jcodemunch", |
There was a problem hiding this comment.
Evidence uses a different protocol
The saved jCodeMunch URL differs from the committed protocol, although aggregateEvidence copies that URL directly from the protocol. The checked-in run therefore does not match the supplied inputs. Regenerate the evidence from the committed files and add a test checking the recorded fixture hashes against them.
Knowledge Base Used: Evaluation and ContextBench
| const manifest = loadJson(manifestPath); | ||
| const protocol = loadJson(protocolPath); | ||
| const errors = []; | ||
| if (manifest.tasks.length !== 18) errors.push(`expected 18 tasks, found ${manifest.tasks.length}`); |
There was a problem hiding this comment.
Suite falls below required minimum
The validator requires exactly 18 tasks, but the repository's evaluation rules require “Minimum 20 queries.” The fixture test also locks in 18. Expand the suite, update the count checks, and rerun the benchmark. This repository requirement must be satisfied before merging.
Context Used: AGENTS.md (source)
| console.log(` protocol sha256: ${sha256File(protocolPath)}`); | ||
| } | ||
|
|
||
| async function runLane(laneId, manifest, repoCheckouts) { |
There was a problem hiding this comment.
Harness lives outside required folder
The new runner, lanes, and scoring code live under scripts/, but the repository's public evaluation rule says “Full eval harness code must be in tests/.” Move the implementation under tests/ and keep only a thin command entry point in scripts/. This repository requirement must be satisfied before merging.
Context Used: AGENTS.md (source)
| - **Payload size vs Aider / jCodeMunch:** median-style averages **642** estimated tokens vs **95** (Aider) and **202** (jCodeMunch) on the same queries. | ||
| - **Query latency vs ripgrep:** **928 ms** average query time vs **76 ms** for the ripgrep baseline (no index). | ||
| - **Edit-preflight slice:** **67%** top-3 here, but still below perfect; broad unsafe tasks are out of scope for this table (see edit-preflight fixtures for abstention tests). | ||
| - **Cross-repo variance:** symbol-retrieval top-3 was **83%** on the two TypeScript repos but **50%** on FastAPI in this run (see `byNiche` in the evidence JSON). |
There was a problem hiding this comment.
Language results are reported incorrectly
The saved results show three symbol-retrieval hits out of four for the TypeScript repositories, or 75%, and two out of two for FastAPI, or 100%. The 83% in byNiche covers all repositories, not just TypeScript. This bullet reverses the comparison; update it to match the saved task results.
| if len(top_files) >= limit: | ||
| break | ||
| payload = json.dumps( | ||
| {"mentionedIdents": mentioned, "rankedTags": len(tags), "topFiles": top_files}, |
There was a problem hiding this comment.
Query words earn usefulness credit
Aider's scored payload includes mentionedIdents, which echoes the query rather than retrieved information. scoreTaskResult searches the whole payload for expected signals, so words such as "dependency" and "router" earn usefulness credit merely because the user asked about them. Keep echoed query fields out of the payload used for usefulness scoring.
Adds a frozen 18-task benchmark across angular-spotify, Excalidraw, and FastAPI covering team-convention lookup, edit-preflight navigation, and symbol retrieval.
npm run benchmark:niche(scripts/run-niche-benchmark.mjs) clones pinned repos, runs five credited lanes, writesresults/niche-benchmark-evidence.json.tests/fixtures/niche-benchmark-manifest.jsonandniche-benchmark-protocol.json(frozen before this run; no post-hoc expected-pattern edits).docs/benchmark.mdupdated with aggregate numbers, rerun instructions, and explicit places Codebase Context loses (team-convention file ranking, latency vs ripgrep, payload size vs Aider/jCodeMunch).tests/niche-benchmark.test.tsguards fixture shape and scoring aggregation.Headline results from the checked-in evidence (2026-10-30): Codebase Context 50% top-3 hit rate vs Aider 22%, Repomix 11%, jCodeMunch/ripgrep 5.6%; avg query latency 928 ms vs ripgrep 76 ms; avg tokens 642 vs Aider 95.
Does not publish to npm; extends existing eval/discovery harness patterns rather than replacing ContextBench families below in the doc.