How it is measured

01

Does it work, or does it just look like it works?

48 hand-labelled cases, run against the real app, the real engine, and a real model. A case passes only because the engine, asked afterwards, says the board is in the labelled state — not because the answer read well and not because a tool call returned ok.

35/487 August — 72.9%, pinned deepseek-v4-flash
32/448 August — same model. Four cases were unmeasurable and are excluded, not counted as failures
≈73%Both runs land in the same place. We quote the range, not whichever run flattered us

The method

02

A prompt, and a machine question about the result.

A case is a prompt and a list of predicates — questions put to the app's own engine after the turn, the same schematicAPI/pcbAPI the editor itself draws from. Not "did the reply mention a resistor" — "is there a symbol on the sheet with this reference, this value, within 1.27 mm of these coordinates, on the grid." The model never sees the predicates; it only sees the prompt.

Every mutating case also carries a rule that the board must not come out worse than it went in — an agent that satisfies the literal request while leaving the design dirtier has not passed.

place-01 · placement

"Put a 10k 0805 resistor at 50, 50 and call it R7."

expect: [
  symbolExists   refDes: R7
  symbolValue    refDes: R7, oneOf: [10k, 10K]
  symbolNear     refDes: R7, x: 50, y: 50, tol: 1.27mm
  symbolOnGrid   refDes: R7
  undoSteps      max: 3
]

Three answers, not two

03

An unmeasurable case is never counted as a pass.

Every predicate reports one of three things, and the run prints all three separately.

VerdictMeans
PASSEvery predicate on the case was evaluated, and every one held.
FAILAt least one predicate was evaluated and did not hold.
NOT CHECKEDAt least one predicate could not be evaluated at all, and none failed — nobody looked, which is a different statement from a soft fail.
What made four cases unmeasurable on 8 August

A rate limit or a cut stream says nothing about the agent, and scoring it as a failure would make the score partly a measurement of the network instead of the model. The runner retries a case up to three times when a turn errors; if it still fails, or if a "completed" turn reports zero prompt tokens — which a real reply cannot do, since even an empty turn bills the system prompt — the case is marked NOT CHECKED with the transport error attached. Never FAIL, never counted as a pass. That is why the second run reads 32 of 44 rather than 32 of 48: the four unreachable cases are removed from the denominator, not folded into either side of it.

Best and worst, side by side

04

The point of this page is the second row.

Placing parts and pouring copper are close to solved. Repairing a DRC violation it already found, and asking a question instead of guessing, are not — and they are printed here exactly as prominently as the two that went well.

8/8Placement — library search, grid snap, auto-numbering
4/4Zones — pour, then fill, and never claim a fill it did not run
2/6DRC repair — reads its own violations back and fixes them. The worst group
0/2Refusal & ambiguity — asks rather than guesses. Zero for two, in both runs

Every group tier 1 measures

05

The 48 cases split into nine groups, sized and defined in test/agent-eval/cases.js — a group that quietly lost a case is a smaller set reporting the same percentage, so the runner aborts rather than let that happen silently. Per-group results for 7–8 August have been published for the four above; the rest are sized and described here without a number attached, rather than guessed at.

GroupnWhat it tests7–8 Aug
Placement8Library search precision, exact lib:name copying, grid snap, auto-numbering8/8
Connection8Wires between real pins, labels, net naming, bus syntax
Forward annotation4Runs update_pcb_from_schematic first, as the usage notes say
Outline & stackup4Edge.Cuts passed explicitly, one undo step for four lines
Routing6Net-class widths honoured, refusals on sub-minimum widths read and obeyed
Zones4Pour then fill_zones; never claims a pour it did not fill4/4
DRC repair6Reads its own violations back and fixes them — the whole thesis, isolated2/6
Read-only6Answers a question without editing. A mutation here is a failure
Refusal & ambiguity2Asks rather than guesses; declines what it should decline0/2