Skip to content

refactor: dedupe computeSavings via pct helper and persist partial token-benchmark results#1875

Open
carlos-alm wants to merge 1 commit into
fix/issue-1756-dedupe-impact-level-renderingfrom
fix/issue-1757-token-benchmark-dedupe-persist
Open

refactor: dedupe computeSavings via pct helper and persist partial token-benchmark results#1875
carlos-alm wants to merge 1 commit into
fix/issue-1756-dedupe-impact-level-renderingfrom
fix/issue-1757-token-benchmark-dedupe-persist

Conversation

@carlos-alm

Copy link
Copy Markdown
Contributor

Summary

  • computeSavings reimplemented the percentage-reduction formula inline instead of using the pct helper already defined for computeAggregate. Promoted pct to module level and adopted it in both places — confirmed bit-for-bit identical behavior via a 10-case equivalence harness (normal, zero-cost, negative savings, zero/negative baseline, rounding edge cases).
  • main()'s per-issue loop only serialized results after the full loop completed, so a crash partway through discarded all already-computed results. Added writePartialResults, called after each issue, overwriting a token-benchmark.partial.json snapshot; removed only after the full run (including optional perf benchmarks) succeeds, so a late failure still leaves the per-issue safety net intact.

Closes #1757

Test plan

  • npm test — full suite green (3519 passed, 0 failed) — this script has no existing test coverage (confirmed via grep)
  • npx tsc --noEmit — clean
  • scripts/ is outside Biome's lint scope by design (biome.json's files.includes is src/**/tests/**) — confirmed no lint tool applies here
  • Built throwaway verification harnesses (not committed): formula-equivalence (10 cases, byte-for-byte match old vs new) and persistence-mechanism (3 scenarios — full success, crash mid-run, crash on first issue — all 13 assertions passed)
  • Ran the real script directly to confirm no syntax/reference errors; skipped the actual multi-issue benchmark run since it requires network + an API key + real spend

Stacked on #1874 (base branch fix/issue-1756-dedupe-impact-level-rendering) — only the token-benchmark.ts/.gitignore diff is this issue's change.

…ken-benchmark results

computeSavings reimplemented the percentage-reduction formula inline
instead of using the pct helper already defined for computeAggregate.
Both call sites now share pct — verified byte-identical output across
normal, zero-denominator, negative-savings, and null-guard cases.

main()'s per-issue loop only serialized results to stdout after the
full loop completed, so a crash partway through (another issue
throwing, or the optional --perf benchmarks failing) discarded every
already-computed result. The loop now overwrites
token-benchmark.partial.json after each issue; the file is removed
once the full run succeeds and the final JSON has been printed.

Fixes #1757

Impact: 5 functions changed, 17 affected
@greptile-apps

greptile-apps Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR promotes the pct percentage-reduction helper from a local arrow function inside computeAggregate to module level and reuses it in computeSavings, eliminating a duplicated inline formula. It also adds per-issue partial result persistence to token-benchmark.ts so a mid-run crash doesn't discard already-computed data.

  • pct extraction: The helper is semantically identical to the previous inline formula in both call sites; the existing guard baselineMedian.inputTokens <= 0 in computeSavings makes the a > 0 check in pct redundant for token savings, but harmless.
  • Partial persistence: writePartialResults overwrites token-benchmark.partial.json after each issue and fs.rmSync cleans it up on a fully successful run; a PARTIAL_RESULTS_PATH entry is added to .gitignore.

Confidence Score: 4/5

Safe to merge; the refactor is behavior-preserving and the persistence logic works correctly for its primary goal of surviving crashes in runIssueExperiment.

The pct extraction is a clean, verified no-op refactor. The partial-results persistence is straightforward and the cleanup path is correct. The only gap is that writePartialResults is not guarded against I/O errors, so a transient disk failure mid-run would abort the benchmark and lose the result for the issue that just finished — the opposite of the intent.

scripts/token-benchmark.ts — specifically the writePartialResults call site and the lack of try/catch around the file write.

Important Files Changed

Filename Overview
scripts/token-benchmark.ts Promotes pct to module scope (semantically identical), simplifies computeSavings, and adds writePartialResults with per-issue persistence; writePartialResults is not wrapped in try/catch, so a write-time I/O error would abort the run and lose the current issue's in-memory result.
.gitignore Adds token-benchmark.partial.json to .gitignore — correct companion entry for the newly introduced partial results file at repo root.

Fix All in Claude Code

Reviews (1): Last reviewed commit: "refactor: dedupe computeSavings via pct ..." | Re-trigger Greptile

Comment on lines +508 to +527
function writePartialResults(results, totalIssues) {
const partialOutput = {
version: benchVersion,
date: new Date().toISOString().slice(0, 10),
model: MODEL,
runsPerIssue: RUNS,
maxTurns: MAX_TURNS,
maxBudgetUsd: MAX_BUDGET,
partial: true,
completedIssues: results.length,
totalIssues,
issues: results,
aggregate: computeAggregate(results),
perfBenchmarks: null,
};
fs.writeFileSync(PARTIAL_RESULTS_PATH, JSON.stringify(partialOutput, null, 2));
console.error(
` Partial results written to ${PARTIAL_RESULTS_PATH} (${results.length}/${totalIssues} issues)`,
);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 If fs.writeFileSync throws (disk full, permission error, path not writable), the exception propagates out of the for loop through main() and into .catch(), which kills the process. The in-memory result that was just pushed to results — and any that haven't been written to a previous partial file — is lost. Wrapping in try/catch lets the run continue and logs a warning instead of aborting.

Suggested change
function writePartialResults(results, totalIssues) {
const partialOutput = {
version: benchVersion,
date: new Date().toISOString().slice(0, 10),
model: MODEL,
runsPerIssue: RUNS,
maxTurns: MAX_TURNS,
maxBudgetUsd: MAX_BUDGET,
partial: true,
completedIssues: results.length,
totalIssues,
issues: results,
aggregate: computeAggregate(results),
perfBenchmarks: null,
};
fs.writeFileSync(PARTIAL_RESULTS_PATH, JSON.stringify(partialOutput, null, 2));
console.error(
` Partial results written to ${PARTIAL_RESULTS_PATH} (${results.length}/${totalIssues} issues)`,
);
}
function writePartialResults(results, totalIssues) {
const partialOutput = {
version: benchVersion,
date: new Date().toISOString().slice(0, 10),
model: MODEL,
runsPerIssue: RUNS,
maxTurns: MAX_TURNS,
maxBudgetUsd: MAX_BUDGET,
partial: true,
completedIssues: results.length,
totalIssues,
issues: results,
aggregate: computeAggregate(results),
perfBenchmarks: null,
};
try {
fs.writeFileSync(PARTIAL_RESULTS_PATH, JSON.stringify(partialOutput, null, 2));
console.error(
` Partial results written to ${PARTIAL_RESULTS_PATH} (${results.length}/${totalIssues} issues)`,
);
} catch (err) {
console.error(` Warning: could not write partial results — ${err.message}`);
}
}

Fix in Claude Code

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Codegraph Impact Analysis

5 functions changed17 callers affected across 5 files

  • pct in scripts/token-benchmark.ts:85 (17 transitive callers)
  • computeSavings in scripts/token-benchmark.ts:429 (3 transitive callers)
  • computeAggregate in scripts/token-benchmark.ts:471 (3 transitive callers)
  • writePartialResults in scripts/token-benchmark.ts:508 (2 transitive callers)
  • main in scripts/token-benchmark.ts:529 (1 transitive callers)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant