Build1 distinct publisher3 min readUpdated
A developer's write-up argues that the missing input in end-to-end failure triage is not a smarter model but named controls a pull request diff can be joined against.
The Engineer · Build desk
Compiled by The EngineerSomething wrong?How this is made
A developer writing on dev.to set out to make CI answer the one question every red end-to-end run raises and no report answers: did the app break, or did the test go stale [1]. That distinction is the whole triage decision, because one answer means stop the merge and fix a regression while the other means the product changed on purpose and the test is describing a version that no longer exists, and both arrive as the same red X [2].
What Playwright actually hands over is a line like `locator('[data-testid="place-order"]') timed out after 5000ms`, which the author calls a fact about a selector rather than a fact about the product [3]. The failure knows the selector, the timeout and the line number; it does not know what `place-order` is, that the button is the last step of a checkout flow, or that the pull request hid it behind a new express-checkout summary [5]. Closing that gap is manual work: open the trace, remember what the button does, find the PR, read the diff, decide [4]. The author's point is that none of this information is hard to obtain, it just never gets written down anywhere a machine can read it [6].
The conventional fix, wrapping actions in `test.step('add two items to the cart')`, produces a nicer report [7]. It fails as an input for two reasons: the string is hand-maintained, so it drifts and then confidently describes behaviour that no longer exists [8]; and it is prose, naming no control and carrying no selector, so there is nothing in it a program can match against a diff [9].
The change is to name the control instead of describing the step, declaring objects such as `new Button(page, 'place-order', 'Place order')` [10]. Each control carries three things: its kind, the selector it resolves to, and the human name [11]. The readable log falls out of that for free [12], but the artifact that matters is a per-action JSON record of action, control type, name, selector and status [13]. The run then leaves behind a record of which parts of the UI the test touched at runtime, which the author distinguishes sharply from which lines of code executed [14].
That gives two sets with a shared key, since a pull request is itself a set of changes to markup and test IDs [15]. Non-empty intersection means the PR changed the exact element the test was reaching for, so the test is stale; empty intersection makes it a regression candidate [16]. The rule is a heuristic on that key: a PR that edits the markup behind a selector and also genuinely breaks it lands in the stale bucket [2].
The anecdote worth keeping is the first attempt, which shipped the error and trace to an LLM [17]. Against a demo PR that deliberately hid the Place order button and removed a cart row, two tests failed [18], and the model returned several well-written paragraphs blaming an unawaited second add-to-cart in a shared `beforeEach` [19]. No such bug existed; the fixture was fine and the PR's own description said the row removal was intentional [20]. The author's reading is that the model reasoned well from insufficient input, since a broken fixture is a reasonable hypothesis given only the symptom [21]. Both failures should have been classified stale under the intersection rule [1].
Worth watching: whether this holds outside test-ID locators, and whether the evidence extends past one demo PR with two failing tests [18].
Follow any of these and your For You feed starts watching them — no settings page required.
Ranked by verification strength, evidence, and original report placement.
Once a failing run records controls by selector, and a pull request is a set of changes to markup and test IDs, there are two sets with a shared key.
Non-empty intersection means the PR changed the exact thing the test was reaching for, so the test is stale; empty intersection means the test failed on something the PR never touched, making it a regression candidate.
Every failing end-to-end run asks the same question and the report never answers it: did the app break, or did the test go stale?
One answer means stop the merge and fix a regression; the other means the app changed on purpose and the test describes a version of the product that no longer exists. Same red X, opposite response.
Playwright reports failures as e.g. Error: locator('[data-testid="place-order"]') timed out after 5000ms, which the author describes as a fact about a selector, not a fact about the product.
Closing the gap is manual: open the trace, remember what the button does, find the PR, read the diff, decide.
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Concrete but single-author and unreplicated
The mechanism is specified precisely enough to check — code samples for control objects, the exact JSON action record, the string-containment join over added and removed diff lines, and a named artifact (razo-steps.json) — and the author volunteers the failure of the earlier LLM-only design plus the remaining unguaranteed step. But all of it rests on one first-person post from one publisher, validated against one self-constructed demo PR, with no independent replication, no repository or test-suite metrics, and no counter-case where the intersection rule was wrong.
No adoption evidence beyond a self-run demo
The supplied source discloses only the author's own run against a demo PR. There are no users, installs, stars, teams, CI pipelines, releases, or third-party deployments reported, so adoption cannot be scored without inventing facts.
Roughly aligned, mildly self-limiting
Claims stay close to what is shown and in places undersell: the author calls the mechanism 'almost embarrassingly simple', publishes the failed LLM-only attempt, admits the classification is still probabilistic, and describes correct current behaviour as an observation rather than a structural guarantee. No product superiority, adoption, or accuracy metrics are asserted. The small negative reflects that the strongest framing ('that distinction is the whole thing') is a design argument the piece then bounds itself, rather than an overreach.
Author promoting own tooling on a self-publishing platform
The piece is a first-person write-up of the author's own system, references its artifact (razo-steps.json) and its PR-comment output, and appears on a developer self-publishing platform where visibility for a personal project is the natural payoff. That creates a moderate self-promotional incentive. Offsetting factors: no pricing, licence, sponsor, employer, or funding relationship is disclosed, and the post volunteers negative results and open gaps, which cuts against pure marketing.
Low-moderate: internally coherent, externally unverified
Confidence is limited by structure, not by internal quality. One source, one publisher, one author, one demo; the descriptive claims about Playwright output and test.step behaviour are checkable and uncontroversial, but everything about whether the selector/diff join reliably separates regressions from stale tests in real repositories is untested here. Derived edge cases remain open, and there is no adoption signal to triangulate against.
build
A Passing AI-Generated Test Is Not Evidence: Seven Checks Before It Enters Your Suite1 distinct publisher
build
The 46GB Leak Your RSS Alert Cannot See: macOS Compressed Memory Breaks Threshold Monitoring1 distinct publisher
build
The prompt never arrived: a Windows batch shim was worth 15 of 24 runs in an agent eval1 distinct publisher
build
Flaky CI is a review standards problem, and this checklist names the three gates1 distinct publisher
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 17, 2026