Skip to content

Commit b4ae108

Browse files
ostenbomclaude
andcommitted
Add Jev screenshot input and a stepwise controller
Benchmark variants now run interleaved per scenario. Adding the page screenshot to the no-gate controller lowered verified passes from 109/150 to 79/150 on Jev 1.14. The stepwise controller (settling, compact history, per-field values, finish vs stop, no-op skipping, ordered aim progress, Escape) reached 150/150 with screenshots and 149/150 without. Three verifiers now check outcomes rather than the final page, and the fault matrix shows no pass with a broken outcome. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 0d085a9 commit b4ae108

13 files changed

Lines changed: 1037 additions & 117 deletions

‎package.json‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
"oxfmt": "0.68.0",
5656
"oxlint": "1.83.0",
5757
"playwright-opentelemetry": "^0.13.0",
58+
"sharp": "0.35.4",
5859
"tsx": "^4.23.15",
5960
"typescript": "^7.0.2"
6061
},

‎pnpm-lock.yaml‎

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎scripts/jev-benchmark.test.ts‎

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { expect, test } from "bun:test";
2-
import { actionCode, candidates } from "./jev-benchmark";
2+
import { actionCode, candidates, select } from "./jev-benchmark";
33

44
test("builds bounded actions from an accessibility observation", () => {
55
const actions = candidates(
@@ -37,3 +37,56 @@ test("keeps action arguments literal", () => {
3737
}),
3838
).toThrow();
3939
});
40+
41+
test("per-field fills take the value Jev chose for that field", () => {
42+
const actions = candidates(
43+
{
44+
url: "https://example.test/checkout",
45+
title: "Checkout",
46+
snapshot:
47+
'- textbox "Name" [ref=e1]: John Doe\n- textbox "City" [ref=e2]\n- button "Pay" [ref=e3]',
48+
},
49+
["John Doe", "New York"],
50+
{ fieldValues: true },
51+
);
52+
expect(actions.filter((action) => action.kind === "fill")).toHaveLength(2);
53+
const answers = {
54+
next: {
55+
type: "choice",
56+
choice: "a0",
57+
probabilities: { a0: 0.5, a1: 0.3, a2: 0.2 },
58+
},
59+
value_a0: { type: "choice", choice: "v0" },
60+
value_a1: { type: "choice", choice: "v1" },
61+
};
62+
// Name already holds its chosen value, so the next most probable action runs.
63+
const selected = select(actions, answers, ["John Doe", "New York"]);
64+
expect(selected?.ref).toBe("e2");
65+
expect(selected?.value).toBe("New York");
66+
expect(actionCode(selected!)).toContain('"New York"');
67+
expect(
68+
select(
69+
actions,
70+
{ ...answers, next: { ...answers.next, choice: "missing" } },
71+
[],
72+
),
73+
).toBeUndefined();
74+
});
75+
76+
test("without per-field values the chosen action runs unchanged", () => {
77+
const actions = candidates(
78+
{
79+
url: "https://example.test",
80+
title: "",
81+
snapshot: '- button "Go" [ref=e1]',
82+
},
83+
[],
84+
);
85+
expect(
86+
select(
87+
actions,
88+
{ next: { type: "choice", choice: "wait", probabilities: { a0: 0.9 } } },
89+
[],
90+
)?.kind,
91+
).toBe("wait");
92+
});

0 commit comments

Comments
 (0)