feat(benchmark): pinned model/reasoning benchmarking for dispatcher workers #312
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/model-benchmark"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What this adds
A benchmarking subsystem that measures a model and reasoning level under production
conditions — the same dispatcher, worker runtime, session logs and acceptance commands a
real delegated task uses. Answers "what does this model cost me on this backend when it
does real work", not "how fast does one prompt stream".
execution.ts,dispatcher.ts,dispatcher-runtime.ts):Execution.pinnedis a host-only field (never model-facing, nodispatchparameter),submitScheduled(..., pinned)validates it, and the runner strategy honours the pinbefore rules and the classifier.
model-roles.ts):resolveWorkerPin()throws on an unavailable model oran unsupported thinking level instead of falling back to the default model. Unlike
resolveModelRole, a benchmark can never silently measure the wrong model.benchmark/suite.ts): declarative cases, fixture checksums beforesubmission and re-checked afterwards,
taskIsolation: require-new-session.benchmark/runner.ts): submits pinned tasks serially, runs acceptancecommands outside the worker path, collects metrics from the worker's own session logs,
persists every outcome immediately (a crash cannot lose a finished measurement).
benchmark/metrics.ts): turns/tokens/reasoning chars/model time/tool calls,summed across attempts including runtime restarts.
benchmark/epoch.ts): build revision +models.json+ settings drop-in hashes;epochDifferences()refuses cross-epoch comparisons./benchmark [list|status|report [suite]|<suite>]starts arun detached, delivers per-outcome progress and the median/p95 table afterwards.
benchmarkblock (enabled/capacity/repeats/caseTimeoutMs), intentionallynot live-reloadable and not field-mergeable — a running measurement must not have its
conditions changed under its feet.
docs/benchmark.md.Why
Three Qwen configurations on the homelab backend (
off/medium/xhigh) were compared byhand and the first attempt produced unusable numbers: a forced-format prompt penalised the
non-thinking run, and one worker whose fixture had vanished reconstructed it from the parent
session transcript (11 of 21 tool calls were a rescue detour). This makes the comparison
reproducible and makes both failure modes structurally visible instead of silently polluting
the table.
Verification
npm test, incl.build + plugin materialise + runtime wiring contracts).
tsc --noEmitclean.sessions/dispatch_33d9cbfe-*/— 6 turns, 34752 input, 5922 output tokens, 9868 reasoningchars, 381821 ms model time, 8 tool calls — exact match with the parser output. Corrupted
lines (bad JSON, record without
totalTokens, array line) are ignored, not fatal.pin fails the run instead of falling back.
expectations never appear in the submitted task text, a run with a live sibling task is
refused, timeouts cancel the task and still persist.
progress + final table delivery, and failures reported instead of dying silently.
Known limits (documented in docs/benchmark.md)
reasoningCharsis a budget proxy, not tokens — the backend returns no thinking-usage data.durationMsis the sum of per-turn model time; wall clock is stored separately so queueingand model time stay distinguishable.
kept out of the task text and drift is detected, but a motivated worker could still locate
a suite file on disk — the coordinator verifies completed work independently regardless.
Not in this PR
No default-config changes (role levels, review thinking, dispatcher capacity) — those are
measurements decisions, and the point of this branch is to produce those measurements first.
feat(benchmark): pinned model/reasoning benchmarking for dispatcher workersto WIP: feat(benchmark): pinned model/reasoning benchmarking for dispatcher workersc24646970ctof8851e44d1A first measurement attempt on the live backend exposed four defects in the benchmark subsystem itself, not in the measurement: - verified required zero fixture changes, so a coding case that legitimately fixed its deliverable could never count. Changes are now split into fixed (declared deliverable), tampered (frozen file, disqualifying) and extra (added file, reported only). - nothing proved which model and level actually ran. The worker session log is now compared against the pin (pinMatches); a run at another level is excluded instead of averaged in. This caught a run submitted as off that ran medium. - a case that is already solved, or that its own reference fix cannot solve, was measured anyway. A preflight now checks the instrument before any worker time is spent and reports preflight-failed without submitting. - grading lived only in the workspace, which workers can read. verifier runs from a private directory outside it, with {workspace} as the only bridge, and naming it in the task text is rejected. Suite gains deliverables, verifier and referenceSolution (fingerprinted, so comparability reflects the grading side too). Docs: the quick-start YAML used fields the parser never accepted; it is corrected and the case contract, the preflight and the five integrity gates are documented. Tests: 1728 pass, 1 skipped, tsc clean.WIP: feat(benchmark): pinned model/reasoning benchmarking for dispatcher workersto feat(benchmark): pinned model/reasoning benchmarking for dispatcher workersc3fb8dbc79toff2d7069d5