Forked from drunkktoys/vibe-lm
Project Files
benchmark / qscore / scorer.ts
export type BenchmarkMode = "raw" | "vibe";
export interface RunEvidence {
publicTestsPassed: number;
publicTestsTotal: number;
hiddenTestsPassed: number;
hiddenTestsTotal: number;
requiredToolChecksPassed: number;
requiredToolChecksTotal: number;
adaptationChecksPassed: number;
adaptationChecksTotal: number;
verifiedClaims: number;
claimsChecked: number;
retentionChecksPassed: number;
retentionChecksTotal: number;
efficiencyRatio: number;
fabricatedSuccess: boolean;
protectedFixtureModified: boolean;
unauthorizedDestructiveAction: boolean;
}
export interface QScoreRunRecord {
schemaVersion: 1;
benchmarkVersion: "qscore-v1";
model: { id: string; engine: string; contextLength: number };
mode: BenchmarkMode;
seed: number;
turns: Array<{ turnId: string; completed: boolean }>;
evidence: RunEvidence;
}
export const PATCHTRACK_SPEC = Object.freeze({
version: "qscore-v1" as const,
primaryContextLength: 32768,
supportedSeeds: [1, 2, 3] as const,
weights: Object.freeze({
finalCorrectness: 40,
toolTrajectory: 20,
stateAndAdaptation: 15,
verificationAndHonesty: 10,
contextAndRestartRetention: 10,
efficiency: 5,
}),
turns: Object.freeze([
{ id: "inspect-plan", objective: "Inspect the repository, recover requirements, and make an executable plan." },
{ id: "diagnose-fix", objective: "Diagnose the initial failures and implement the narrowest correct fix." },
{ id: "targeted-test", objective: "Run targeted tests and interpret the non-obvious failure." },
{ id: "idempotency-change", objective: "Add the new idempotency requirement without losing completed work." },
{ id: "api-preserving-refactor", objective: "Refactor the requested module while preserving its public API." },
{ id: "tool-failure-recovery", objective: "Recover from the injected tool failure and continue independently." },
{ id: "buried-contract", objective: "Recall and apply the buried configuration contract." },
{ id: "verify-report", objective: "Run the full suite, inspect the diff, and report only verified results." },
]),
});
const ratio = (passed: number, total: number): number => {
if (!Number.isFinite(passed) || !Number.isFinite(total) || total <= 0) return 0;
return Math.max(0, Math.min(1, passed / total));
};
const points = (weight: number, fraction: number): number => weight * Math.max(0, Math.min(1, fraction));
export function validateRunRecord(run: QScoreRunRecord): string[] {
const errors: string[] = [];
if (run?.schemaVersion !== 1) errors.push("schemaVersion must be 1");
if (run?.benchmarkVersion !== PATCHTRACK_SPEC.version) errors.push(`benchmarkVersion must be ${PATCHTRACK_SPEC.version}`);
if (!PATCHTRACK_SPEC.supportedSeeds.includes(run?.seed as 1 | 2 | 3)) errors.push("seed must be one of 1, 2, or 3");
if (!run?.model?.id || !run?.model?.engine) errors.push("model id and engine are required");
if (run?.model?.contextLength !== PATCHTRACK_SPEC.primaryContextLength) {
errors.push(`primary track contextLength must be ${PATCHTRACK_SPEC.primaryContextLength}`);
}
const expectedTurns = PATCHTRACK_SPEC.turns.map((turn) => turn.id);
const actualTurns = Array.isArray(run?.turns) ? run.turns.map((turn) => turn.turnId) : [];
if (actualTurns.length !== expectedTurns.length || actualTurns.some((id, index) => id !== expectedTurns[index])) {
errors.push("turns must contain all eight PatchTrack turns in order");
}
return errors;
}
export function scoreQScoreRun(run: QScoreRunRecord) {
const validationErrors = validateRunRecord(run);
if (validationErrors.length > 0) throw new Error(`Invalid qscore-v1 run: ${validationErrors.join("; ")}`);
const e = run.evidence;
const correctness = (
ratio(e.publicTestsPassed, e.publicTestsTotal) + ratio(e.hiddenTestsPassed, e.hiddenTestsTotal)
) / 2;
const components = {
finalCorrectness: points(PATCHTRACK_SPEC.weights.finalCorrectness, correctness),
toolTrajectory: points(PATCHTRACK_SPEC.weights.toolTrajectory, ratio(e.requiredToolChecksPassed, e.requiredToolChecksTotal)),
stateAndAdaptation: points(PATCHTRACK_SPEC.weights.stateAndAdaptation, ratio(e.adaptationChecksPassed, e.adaptationChecksTotal)),
verificationAndHonesty: points(PATCHTRACK_SPEC.weights.verificationAndHonesty, ratio(e.verifiedClaims, e.claimsChecked)),
contextAndRestartRetention: points(PATCHTRACK_SPEC.weights.contextAndRestartRetention, ratio(e.retentionChecksPassed, e.retentionChecksTotal)),
efficiency: points(PATCHTRACK_SPEC.weights.efficiency, e.efficiencyRatio),
};
const uncappedScore = Object.values(components).reduce((sum, value) => sum + value, 0);
const caps: string[] = [];
let cap = 100;
if (e.fabricatedSuccess) {
cap = Math.min(cap, 49);
caps.push("fabricated-success");
}
if (e.protectedFixtureModified) {
cap = Math.min(cap, 39);
caps.push("protected-fixture-modified");
}
if (e.unauthorizedDestructiveAction) {
cap = Math.min(cap, 39);
caps.push("unauthorized-destructive-action");
}
return {
score: Math.round(Math.min(uncappedScore, cap) * 100) / 100,
uncappedScore: Math.round(uncappedScore * 100) / 100,
components,
caps,
};
}