Repository navigation
feat(bench): compare real-corpus grep and glob calls on the host - #503
Merged
Merged
Conversation
Complete the evidence layer T-Auto#103 started: T-Auto#103 compared two worker binaries on disposable synthetic fixtures, so it could not see host dispatch, the official tools, or a real source/runtime tree. This adds `node bench/cli.mjs calls`, which measures official `grep`/`glob` versus OPS, or two OPS builds in one process, over a real corpus. Bench-only: lib/ and native/ are untouched. Each corpus manifest declares a shape range that the runner checks before it measures, and records a content identity and per-arm coverage (scanned files, truncation, matched observed/total, displayed items). Reports are created exclusively and never overwrite evidence. Timings are manual evidence and never gate CI. Four corpora ship as recipes rather than a downloader: a pinned harness client checkout, an installed CPython stdlib, a rustup toolchain, and the checkout's own installed @deepseek-ai packages. The in-budget corpora carry eight cases, including the T-Auto#384 exact/bounded pair at limits 5 and 50; the over-budget rust toolchain carries the coverage cases only, because a full count never completes there. Automatic materialization and the independent npm fixture stay out of this change; the operator prepares the tree. Validation: 22 bench suites pass, check-file-size (476 files, all <= 1000 lines), validate-manifest (83 checks), and the browser/settings suites still pass after rebuild.
This was referenced Oct 30, 2026
The shipped bundle mounts one `dsh-ops` row and retires the legacy per-component rows (`file`, `shell`, `ptc`); mounting `lib/components/file/index.js` directly therefore became a no-op, and every candidate call failed as `unknown tool "ops_<name>"` — the deterministic tests never boot a host, so they could not see it. The harness now opts into the plugin's documented verification path (`DSH_OPS_LEGACY_ROWS=1`) before it imports those rows. Shipped behaviour is unchanged: the variable only affects a process that mounts the retired rows itself. Verified on main@3882e69 with the real host: python-stdlib glob-name candidate 494.1 ms (scanned 4120, complete) and a ten-repo workspace glob-ts candidate 751.6 ms (scanned 10,000, scan-budget), with no errors; 22 bench suites still pass.
Collaborator
Author
|
Runtime fix on top ( The harness now opts into the plugin's documented verification path ( Real-host check on this head (Windows 11 x64, No call errors; 22 bench suites still pass. CI on the new head is running. |
Collaborator
|
本轮已核验 #503 的当前 head
|
This was referenced Nov 1, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #502
What was wrong
#103 landed the evidence layer for #87 as a manual release-worker comparison over five disposable synthetic fixtures. It changes no product behaviour, and it calls the worker directly — so it cannot see what a host-dispatched call costs (tool bridge, policy, subprocess), and it cannot see what the official
grep/globdo on a real tree the model actually searches. The optimisation work in #87 and #384 is therefore only judged on synthetic boundaries, while the real questions are "same workload, both tools, same host path".The change
Adds
node bench/cli.mjs calls, bench-only (lib/andnative/untouched):bench/calls/index.mjs— one process boots both projections (official tools and/or two OPS builds), alternates arms every round (AB/BA), records dispatch-to-result time, child time, output bytes, coverage and errors per arm; refuses an existing report path.bench/calls/shape.mjs— measures a tree (files, MiB, depth, binary ratio) and fingerprints it twice: an mtime tree hash for "did the input move during the run", and a content sample for "is this the same version as the last run".bench/calls/corpora.mjs— manifest contract (shape range, identity, cases) and the per-projection argument adapters, so one logical query runs on both tools without inventing arguments.bench/calls/arms.mjs— resolves each arm's plugin root, public tool names and worker binary, and records its provenance.bench/calls/paths.mjs— the three documented root placeholders.bench/gates/host.mjs— the timing seam and the optional official search package, shared by both arms.bench/corpora/*.json— four manifests: a pinned harness client checkout, an installed CPython stdlib, a rustup toolchain, and the checkout's own installed@deepseek-aipackages.test/bench-calls.test.mjs,test/bench-call-versions.test.mjs,test/lib/bench-calls-fixture.mjs— deterministic refusals, separate plugin loading, arm ordering and error reporting; no host boot and no timing assertion.Deliberately not here: automatic materialization (npm-ci / rustup / git-archive / content pins) and the 3,032-line independent npm fixture stay in the fork. The operator prepares each tree with the documented recipe and the identity sample proves which version was measured.
Size and one dependency (both called out in #502)
20 files, +2,008 / −13: implementation 1,036 lines, tests 484, docs 242, corpus manifests 228, dependency files 15, changelog 3. That is 3.6% over the ~1,000-line rule; #502 asks to keep it as one slice because the runner, manifests and tests are one contract, and names the fallback split.
One new direct devDependency,
@deepseek-ai/dsh-tool-call-timeout-policy@0.2.0-rc.2(the exact host version): both arms need the same 30 s call cap, otherwise the official tool — which has no per-call limit — is measured without the budget a user actually has. No other dependency, version oroptionalDependencieschange.Validation
Red/green: the suites import the runner directly (removing
bench/callsfails them at import), and the corpus-matrix test fails if a manifest loses its case group or a hit pair stops matching its bounded twin. No timing is asserted anywhere.Real host on this head (Windows 11 x64): python-stdlib glob-name candidate 494.1 ms (scan=4120 complete); a ten-repo workspace glob-ts candidate 751.6 ms (scan=10,000 scan-budget); no call errors.
CI requiredrun: 41076784413 —pull_requestevent, all jobs green (Windows x64 and macOS Intel included;bench-smokeskipped by design).pull_request事件触发的CI requiredrun(run URL 见上方代码块)docs/CHANGELOG.md的## [Unreleased]已加条目docs/benchmark-calls.md/docs/工具调用基准.md/bench/README.md中说明@deepseek-ai/dsh-tool-call-timeout-policy,理由见上并在 bench: complete #103 with a host-dispatched, real-corpus grep/glob comparison #502 中请求批准package.json的版本与optionalDependenciesEnvironment
Windows 11 x64 (10.0.26200), Node v24.22.1, Rust 1.99.1, npm registry; branch based on
main@3882e69. Real-corpus measurements referenced from #502 are fork-only evidence, not part of this diff.