Both builds end on the same frame
A test that compares final screenshots passes this change. The last frame of the broken build is the last frame of the good build, pixel for pixel. The bug is in the 240 ms after Inspect reopens the panel, where 15 recorded frames differ and then stop differing.
The broken build keeps the position of the Inspect button from the first time the panel opens. After the window changes size, the panel grows from that old spot, 80 px to the right, and slides home. It is one of the seeded bugs, in a small inspector fixture on a corpus I wrote.
=4800 msThe last frame of each build is the same frame
One row of pixels, from every frame
The two tall pictures on the stage are slit scans. Each one takes the same single row of pixels out of every recorded frame and stacks the rows in time order, oldest at the top, so a whole session is one image. A panel that opens draws a funnel. A window that narrows draws a step. A frame that was held draws a seam.
The good build draws the same funnel every time the panel opens. The broken build draws it once more at the bottom, pushed to the right and flat against the edge of the window, and the dashed line beside it is where the recorded rectangles say it should have been. The shading over each picture is drawn from those rectangles too, so the panel can be told from the page around it. Move the scan line up to the row through Inspect, and the broken panel starts in line with where Inspect stood at the top of the picture, before the window changed size.
Each build is judged on its own
Trace does not diff the two builds. A scenario states what must stay true, and each build is replayed under the same controlled clock and judged against that list alone. Here the broken build breaks one requirement and the good build breaks none, and that pair of results is the verdict.
| Requirement, as the scenario states it | Last good build | Broken build |
|---|---|---|
The latest request owns panel{"kind": "latest-request-wins", "key": "panel", "terminal": ["open", "closed"]} | Held | Held |
Focus never sits on a hidden, inert or detached element{"kind": "focus-valid"} | Held | Held |
Panel appears at trigger or at its final position (within 4 px){"kind": "geometry-origin", "target": "panel", "anchor": "trigger", "tolerancePx": 4} | Held | Broken, 80 px off at 4000 ms |
Panel stays 8 px inside the viewport after a resize{"kind": "geometry-fits", "target": "panel", "insetPx": 8, "tolerancePx": 2} | Held | Held |
Only one live panel exists at a time{"kind": "single-interactive", "target": "panel"} | Held | Held |
On the corpus I tuned, comparing two full traces also finds every seeded bug, so requirements catch nothing extra there. What they do is stay quiet: a comparison flags most legitimate changes, because a change is a difference, and it has nothing to say when both builds share a bug.
What was measured
Every number here comes from a saved run in the repository, on fixtures and seeded bugs I wrote myself. The corpus is small, so these show that the tool does what it says on code it was built beside, and little about code it has never seen.
Held-out fixtures
6 of 6seeded bugs caught1 of 4clean builds wrongly flagged
- Seeded bugs
- Clean builds
Tuned corpus
18 of 18for Trace, and for a plain comparison
- Trace
- Comparing two traces
Reduction
14 to 4actions, written by hand18 to 2generated
- The session on this page
- A generated session
- Fresh runs
- Baseline runs
Random sessions
2 of 295sessions on correct builds flagged
Run it on your own component
Mark the elements you care about with data-trace-id, write a scenario that says what the user does and what must stay true, and register both builds in a fixture manifest. Then one command replays the scenario on the two builds and writes a report like the one behind this page.
pnpm trace fixtures add path/to/fixture.jsonpnpm trace run my.scenario.json --baseline tabs@main --candidate tabs@branchThe README has the setup, and the scenario guide lists every action and requirement.
Limits
These are the things this page does not show, in the order they matter. The longer list is in the repository.
- The corpus is small and I wrote it, so it says nothing about how many real bugs Trace would catch
- The holdout ran once on an earlier oracle, and no result tests the final oracle on unseen code
- Trace only finds what a scenario reaches, and a requirement it never reaches reads as not exercised
- Controlled time does not hold every channel, such as workers and ResizeObserver delivery
- Timings are lab numbers from one machine, and they are not INP
- Nobody outside this project has used it yet
Read the report Trace wrote
The frames are screenshots of the real fixture, taken by Trace on a rerun of the saved scenarios and kept only because the rerun recorded the same geometry as the saved report. The frames and the slit scans are those screenshots, and Difference lights the pixels where the two builds disagree. The dashed outlines, the ruler, the shading and the note over the slit scans, and everything in Geometry are drawn from the rectangles in that report, and nothing in the pictures under them is changed. Playback slows down at the failure and skips the quiet stretches, and the clock always shows the recorded time.