fix(performance): treat a counter/wall-clock type switch as a weakening

Turning `{ value: 100, slack: 10 }` into `{ value: 105, toleranceRatio: 1 }`
skipped the raised-counter-value rule and was reported as a lowered limit.
Switching an entry between counter and wall-clock now needs the
perf-baseline-increase label.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0166PWobUjpoiWt8E9bBdsCs
This commit is contained in:
Claude committed 2026-09-28 06:18:09 +00:00
1 parent e63173353d
commit 2079b59a66
3 files changed
+42 -2

No files matched your search

+3 -2
View File
@@ -359,8 +359,9 @@ The job also refuses a weakened baselines file:
entry's enforced limit (`value × toleranceRatio` or `value + slack`) went up,
a tolerance or slack widened or an entry disappeared, so a PR cannot grow the
payload and raise the baseline to match. A counter's `value` may not go up
either, even when narrower slack lowers its limit. Lowered limits and new
entries pass.
either, even when narrower slack lowers its limit, and switching an entry
between counter and wall-clock (adding or removing `toleranceRatio`) counts
as a weakening too. Lowered limits and new entries pass.
Baselines only move down. Lower `value` in the same PR as the change that
earned it, set `updatedAt` and `evidencePr`, and paste the measurement output
@@ -9,6 +9,8 @@
* or `value + slack`) went up, whose tolerance or slack widened, or that
* disappeared, is a failure. A counter's `value` may not go up either, even
* when narrower slack lowers its limit: the value is the measured evidence.
* Switching an entry between counter and wall-clock (adding or removing
* `toleranceRatio`) is a weakening too, so that rule cannot be sidestepped.
* New entries and lowered limits pass.
*
* `--allow-increase` turns those failures into printed "allowed" lines. CI
@@ -81,6 +83,8 @@ export function compareBaselineDirection({
);
continue;
}
const kind = (entry) =>
entry.toleranceRatio === undefined ? 'counter' : 'wall-clock';
const baseTolerance = baseEntry.toleranceRatio ?? 1;
const headTolerance = headEntry.toleranceRatio ?? 1;
const baseSlack = baseEntry.slack ?? 0;
@@ -91,6 +95,10 @@ export function compareBaselineDirection({
weakened.push(
`${label}: toleranceRatio widened from ${baseTolerance} to ${headTolerance}. Tolerances are a maintainer decision (the ${BASELINE_INCREASE_LABEL} label); a PR may only narrow them.`
);
} else if (kind(baseEntry) !== kind(headEntry)) {
weakened.push(
`${label}: changed from a ${kind(baseEntry)} entry to a ${kind(headEntry)} entry. The two are read from different summary sections and compared differently, so a type change is a maintainer decision (the ${BASELINE_INCREASE_LABEL} label).`
);
} else if (headSlack > baseSlack) {
weakened.push(
`${label}: slack widened from ${formatNumber(baseSlack)} to ${formatNumber(headSlack)}${unit}. Slack is a maintainer decision (the ${BASELINE_INCREASE_LABEL} label); a PR may only narrow it.`
@@ -213,6 +213,37 @@ test('a counter value raised behind narrower slack still fails', () => {
assert.equal(allowed.allowed.length, 1);
});
test('switching an entry between counter and wall-clock fails', () => {
const counterToWallClock = compareBaselineDirection({
base: file(100, { x: { value: 100, slack: 10 } }),
head: file(100, { x: { value: 105, toleranceRatio: 1 } }),
});
assert.equal(counterToWallClock.failures.length, 1);
assert.deepEqual(counterToWallClock.lowered, []);
assert.match(
counterToWallClock.failures[0],
/launch\/x: changed from a counter entry to a wall-clock entry/
);
const wallClockToCounter = compareBaselineDirection({
base: file(100, { x: { value: 100, toleranceRatio: 1.25 } }),
head: file(100, { x: { value: 90 } }),
});
assert.equal(wallClockToCounter.failures.length, 1);
assert.match(
wallClockToCounter.failures[0],
/changed from a wall-clock entry to a counter entry/
);
const allowed = compareBaselineDirection({
base: file(100, { x: { value: 100, slack: 10 } }),
head: file(100, { x: { value: 105, toleranceRatio: 1 } }),
allowIncrease: true,
});
assert.deepEqual(allowed.failures, []);
assert.equal(allowed.allowed.length, 1);
});
test('allowIncrease reports every weakening as allowed instead of failing', () => {
const result = compareBaselineDirection({
base: file(100, { cdTicks: { value: 5 } }),