Back to home@Muredsa

dsh-benchup

Install with npm i dsh-benchup. Reproducible, profile-aware benchmarks for DeepSeek Harness — compare models, plugins, prompts, and agent strategies.

Stars
0
Language
TypeScript
Created
Aug 26, 2026
Updated
Aug 26, 2026

Introduction

DSH BenchUp

English | Русский | 简体中文

npm version CI license Node.js

Reproducible, profile-aware benchmarks for DeepSeek Harness.

DSH BenchUp answers one practical question: did this change make the agent better, or merely more expensive? It runs the same scenarios across models, profiles, prompts, compaction strategies, subagent setups, and plugins — then compares the evidence without collapsing it into a single misleading score.

What it measures

DimensionSignals
Qualitytask success, exact output, tests, files, JSON Schema
Efficiencyinput/output tokens, LLM turns, tool calls, repeated work, wall time
Robustnessretries, errors, timeouts, variance across repetitions
Diagnosticsnamespaced metrics contributed by the plugin under test

Install

npm i dsh-benchup

For a Harness benchmark, install the package in every profile that BenchUp will start. The commands below do this through DSH, so the dependency is placed in the right profile directory.

Quick start

BenchUp has a CLI and a temporary observer plugin. Install dsh-benchup from npm into every Harness profile that a benchmark starts; it is deliberately a plain dependency, not an always-on dsh.bundle, so normal sessions are never traced.

Installed Harness

When dsh is installed on your PATH, use its profile-aware installer. It initializes the built-in headless profile on first use and works whether or not DSH_HOME is set:

dsh plugin --profile headless add dsh-benchup

DSH may print declares no dsh.bundle; that is expected for BenchUp. Resolve the profile directory with the same fallback DSH uses, then run the installed local CLI:

$dshHome = if ([string]::IsNullOrWhiteSpace($env:DSH_HOME)) { Join-Path $HOME '.dsh' } else { $env:DSH_HOME }
$profile = Join-Path $dshHome 'profiles\headless'
$experiment = 'C:\path\to\benchmarks\examples\basic-experiment.yml'
$output = 'C:\path\to\benchmarks\.dsh-benchup'

Push-Location $profile
try { pnpm exec dsh-benchup run $experiment --output $output } finally { Pop-Location }

The included basic-experiment.yml is a one-run smoke benchmark using only headless; it needs the model credentials and default provider that your Harness profile normally uses.

Harness source checkout

For a cloned Harness repository, do not run pnpm dsh from an arbitrary directory. Run the installer from the checkout, then pass --dsh-source to BenchUp. This invokes the checkout's node --import tsx/esm launcher while still giving the agent an isolated benchmark workspace:

$harness = 'C:\path\to\deepseek-harness'
$benchmarks = 'C:\path\to\dsh-benchup'

Set-Location $harness
pnpm dsh plugin --profile headless add dsh-benchup

$dshHome = if ([string]::IsNullOrWhiteSpace($env:DSH_HOME)) { Join-Path $HOME '.dsh' } else { $env:DSH_HOME }
$profile = Join-Path $dshHome 'profiles\headless'
Push-Location $profile
try {
  pnpm exec dsh-benchup run (Join-Path $benchmarks 'examples\basic-experiment.yml') --dsh-source $harness --output (Join-Path $benchmarks '.dsh-benchup')
} finally { Pop-Location }

--dsh <command> remains available when a non-default dsh executable is already available. It and --dsh-source are mutually exclusive.

Compare profiles

Create an experiment profile by copying the initialized baseline profile, then install the variant under test. Copying preserves the headless bundle stack; creating an arbitrary new profile with dsh plugin alone starts from the minimal base stack and cannot run headless tasks.

$baseline = Join-Path $dshHome 'profiles\headless'
$experimentProfile = Join-Path $dshHome 'profiles\headless-experiment'
if (-not (Test-Path $experimentProfile)) { Copy-Item $baseline $experimentProfile -Recurse }

dsh plugin --profile headless-experiment add dsh-memcore

Install BenchUp into any profile that was not copied from an already configured profile. To try an unreleased BenchUp revision, substitute github:Muredsa/dsh-benchup for dsh-benchup in the installation command.

dsh-benchup is the supported command in this release. A future DSH application bundle may add the shorter dsh benchup alias without changing experiment files.

An experiment

version: 1
runs: 5
models:
  gpt:
    provider: openai
    model: gpt-5
    temperature: 0
variants:
  baseline:
    profile: headless
  memcore:
    profile: headless-memcore
scenarios:
  - id: coding/auth-fix
    fixture: fixtures/auth
    task: tasks/auth-fix.md
    evaluators:
      mode: all
      checks:
        - type: command
          command: [pnpm, test]
        - type: file
          path: src/auth.ts

Every model runs every compatible variant and scenario. The default paired-shuffled schedule changes cell order deterministically to reduce systematic “first run” effects. Set temperature: 0, pin model IDs and profile dependencies, and use objective evaluators whenever possible.

Multi-episode cold/warm scenarios

scenarios:
  - id: coding/auth-memory
    fixture: fixtures/auth
    episodes:
      - id: create
        task: tasks/01-create-auth.md
        state: { workspace: reset, persistent: reset, session: fresh, process: fresh }
      - id: fix
        task: tasks/02-fix-refresh.md
        state: { workspace: retain, persistent: retain, session: fresh, process: restart }
      - id: new-session
        task: tasks/03-change-policy.md
        state: { workspace: retain, persistent: retain, session: fresh, process: restart }

This models a cold first episode followed by warm persistent memory while each agent process and session is new. The runner exports DSH_BENCHUP_STATE_ROOT; a persistent-memory plugin must use that location to participate in reset/retain control. session: continue and process: reuse are retained in the public schema but intentionally fail in the MVP instead of producing ambiguous data.

Objective evaluators

exact compares the final child stdout with an expected file; it is best for deliberately minimal reply scenarios. command runs explicit argv with no shell. file checks workspace file presence. json validates a workspace JSON document with JSON Schema via Ajv. Evaluators are all by default and may be grouped as any.

LLM-as-a-judge is intentionally not included in the MVP. Add it only as a supplemental evaluator with its own pinned judge model and preserved judgement trace; do not use it as the only definition of success.

Plugin diagnostics

A plugin can register its own numbers through the benchMetrics service:

ctx.benchMetrics.register({
  name: 'memcore.memory_hits',
  unit: 'count',
  aggregation: 'sum',
  dimension: 'diagnostic',
  scope: 'episode',
  description: 'Memory retrievals that produced at least one usable record.',
})
ctx.benchMetrics.add('memcore.memory_hits')

Use namespaces such as memcore.memory_hits, context_manager.injected_tokens, or tool_router.reroutes. Definitions and values are persisted with the trace and independently averaged in comparison.json.

Artifacts and safety

Runs go to .dsh-benchup/runs/<run-id>/ unless --output is supplied. The directory includes the expanded configuration, child patch, per-episode summary, raw session event JSONL, result table, comparison, and Markdown report. A trace may include prompts, responses, paths, and tool arguments; treat it as sensitive.

See the architecture note for lifecycle details, reproducibility rules, and the current MVP limitation.

Development

pnpm install
pnpm check
pnpm build
pnpm exec dsh-benchup --help

Releases

Pushing a version tag such as v0.1.2 starts the Publish to npm GitHub Actions workflow. It validates and builds with Node 24 before running npm publish; it uses npm Trusted Publishing through GitHub OIDC and therefore stores no npm access token in GitHub.

After configuring the trusted publisher once in npm, make a release with:

pnpm check
npm version patch -m "release: v%s"
git push --follow-tags

Use minor or major instead of patch when SemVer requires it. A tag only publishes a version that does not already exist in npm.

Licensed under MIT.