Skip to Content
Vektos
Anecdotes

Twelve percent is not a style

The first grader would have punished agents for fintech data and missed real violations. What a grader counts is a design decision.

Date: 2026-11-08. Context: extending the graders (feat/bench-graders).

What happened

The week 0 grader flagged any string in any object literal that looked like CSS: #fff, 12px, 50%. It had three passing tests, and it looked done.

Before extending it, we ran it on three lines of the kind of data the fintech tasks will use:

{ id: "acc_1", balance: "48,210.00", change: "12%", color: "#2563eb" },
{ id: "acc_2", balance: "9,300.50", change: "-3.5%", apr: "4.25%" },
{ ref: "#a1b2c3", fee: "0.5%" }

Plus a few lines of real styling mistakes. The result:

Old graderNew grader
change: "12%", apr: "4.25%", fee: "0.5%", ref: "#a1b2c3"4 violationsnone
color: "white", <Box bg="#fff">, style={{ marginTop: 12 }}missed3 violations
bg: { _dark: "#0f172a" }reported as property _darkreported as bg

In a fintech task, percentages are everywhere. The old grader would have charged the agent for its data, and the number would have looked like design-system drift. It also did not see named colors, JSX style props or bare numbers in style, which are the most common shortcuts.

The fix is to grade only values that belong to a style property. A key counts when it is a CSS property (camelCase or kebab-case), a Panda shorthand (bg, px, rounded), or a condition (_hover, base, md) under one.

The new grader graded the design system itself next: 40 files, one hit. It was a real raw value, minHeight: "100vh" in the Storybook decorator, which sits outside Panda's include. It now carries a // vektos-ignore with the reason, the first one in the repo.

What we learned

A grader is a definition of "wrong", and a test suite only checks the cases you thought of. Three green tests said nothing about the data the benchmark will actually see. Running the grader on realistic input, and on code we know is right, found more than writing tests did.

The property filter has a blind spot of its own: a data key that happens to be a CSS property. { width: "Width 12px" } is still flagged. { color: "#2563eb" } in a chart series is flagged too, and that one is correct: a chart color should be a token.

What it means for Vektos

1. Every grader gets a reference run. The design system and the web app are graded like agent code in grade.test.ts, and must come out clean. A false positive there fails bun run check.

2. Graders run only on files the agent wrote. Task fixtures are JSON and are never graded. Data the agent writes inline is graded, and the property filter keeps it fair.

3. Report what a score means. "N raw values" is meaningful only next to the rule that produced it. The Violation type carries rule and a message for that reason.

Follow-ups

  • Done: property-aware grading, a shared Violation type, the reference run test.
  • When the five tasks exist, run every grader on a hand-written ideal solution for each task. It must score zero.

On this page