A finding is developer-ready when the person who picks it up can reproduce it, fix it, and prove it is fixed without sending anybody a question. That is the whole test. It sounds modest, and most reports fail it. The fields that carry those three jobs are easy to write vaguely, and nobody notices until a developer is sitting in front of a page that looks fine to them.
The gap costs more than an email. A finding that cannot be reproduced gets closed as works for me. A finding with the wrong rule number on it sends somebody to the wrong guide and they fix a thing that was never broken. And a finding with no acceptance test gets marked done by the person who wrote the code, which is the moment the whole chain of evidence quietly stops meaning anything.
So here is the shape of a finding that survives contact with a sprint board, the seven fields it carries, one worked example written out in full, and the two extra lines that turn a fix into something that stays fixed.
The Seven Fields, and What Breaks Without Each One
Read this as a checklist against the last report you were sent. Every field below has a job, and the third column is what actually goes wrong in a team when the field is missing or written loosely.
| Field | What it has to say | What happens without it |
|---|---|---|
| What the defect is | One plain sentence naming the thing that is wrong, in the words a person would use out loud | The ticket gets rewritten by whoever imports it, and the meaning drifts on the way |
| Where it occurs | The page, the exact element, and the state the page was in when it happened | Somebody opens the page in its default state, sees nothing, and closes the ticket |
| How to reproduce it | The steps, plus the browser and the assistive technology with their versions | A screen-reader bug reproduces on a combination rather than on a product, so a tester on a different pairing marks it invalid |
| The criterion it fails | The number, the name and the level, and more than one where the barrier breaks more than one rule | The developer follows the number to the wrong fix guide and solves a different problem |
| The evidence | A screenshot captured at the moment it was found and dated, plus the markup excerpt where markup is the issue | The finding becomes an assertion, and the first person who disagrees with it wins by default |
| The severity | A band, defined somewhere in the report, and labeled as the auditor's judgment | The board gets sorted by a number nobody can explain, and somebody reports it upward as though a standard said it |
| The remedy and its acceptance test | What to change, then separately how a reviewer confirms the change worked | The fix ships, nobody checks it against anything, and the next audit finds it again |
Only two of those are hard to produce. Reproduction steps take discipline because they have to be written while the failure is on screen rather than reconstructed afterwards, and the acceptance test takes thought because it is a different sentence from the remedy. The rest is a matter of somebody deciding the report is for a developer rather than for a filing cabinet.
A Worked Finding, Written Out in Full
This one is an illustration rather than a client engagement, built from a failure we meet constantly, and it is written the way a finding should arrive. Read the right-hand column as the words that would actually appear in the ticket.
| Field | What this finding says |
|---|---|
| Reference | WR-014 |
| What the defect is | The delivery address form reports an invalid postcode by turning the field border red and nothing else. There is no text explaining what is wrong, so a screen reader user hears nothing and a colorblind user sees nothing. |
| Where it occurs | Checkout step 2 of 4, the postcode field inside the delivery address group. The page only enters this state after Continue is pressed with a malformed postcode, so the default view of the page is clean. |
| How to reproduce it | Add any item to the basket, go to checkout, fill in name and street, type SW1A in the postcode field, press Continue. Chrome 141 with NVDA 2025.3 on Windows 11. NVDA announces the field name and its contents and says nothing about an error. |
| The criterion it fails | 3.3.1 Error Identification, Level A. The error is not identified in text. It is close to 4.1.3 Status Messages and it is not that one, because the problem is that no message exists rather than that an existing message goes unannounced. |
| The evidence | Screenshot of the red-bordered field with no accompanying text, captured August 26, 2026. Markup excerpt showing <input id="postcode" class="is-invalid"> with no aria-invalid, no aria-describedby and no error element anywhere in the form. |
| The severity | Blocker on our four-band scale, defined in this report's introduction. A customer who cannot work out why the form will not proceed does not buy. The band is our judgment of user impact, not a WCAG grade, because WCAG grades a criterion pass or fail and says nothing about how much a failure hurts. |
| The remedy | Render a text error next to the field naming the field and the problem, so Enter a full postcode, for example SW1A 1AA. Give the input aria-invalid="true" and point aria-describedby at the error element's id, so the message is read as part of the field. |
| The acceptance test | With NVDA running, submit the same malformed postcode. Focus lands on the postcode field and the announcement contains the field name, the word invalid, and the error text. Turn off CSS and the error text is still visible and still adjacent to its field. |
Notice what the acceptance test is not. It is not make the error accessible, and it is not the remedy with a tick box beside it. It describes an observation somebody makes, on a named pairing, that comes out the same way for anybody who repeats it. That is what lets a reviewer close the ticket honestly, and it is the same sentence a retest reads six weeks later.
The Criterion Field Is Where Good Findings Go Wrong
Everything downstream hangs off the rule number. It picks the fix guide, it sets the level, and it decides whether the item is inside a legal obligation or outside one. It is also the field an auditor is most likely to get slightly wrong under time pressure. Three mis-filings turn up more than all the others put together.
| The barrier | Commonly filed as | What it actually fails |
|---|---|---|
| A visible label sitting beside a field it was never wired to | 3.3.2 Labels or Instructions | 1.3.1 Info and Relationships. The label is on the screen, which is what 3.3.2 asks for. What is missing is the programmatic association, so a ticket citing 3.3.2 asks a developer to add a label that is already there. |
| A form error the page announces but never writes down | 4.1.3 Status Messages | 3.3.1 Error Identification. The rule asks that the error be identified and described to the user in text. The mirror case, an error written down but never announced, is the one that belongs to 4.1.3, and the two need opposite fixes. |
| A focused control partly covered by a sticky header | A Level AA failure | Nothing at Level AA. 2.4.11 Focus Not Obscured (Minimum) asks only that the component is not entirely hidden. The version that forbids any obscuring at all is 2.4.12 at Level AAA, and almost nobody is being asked to meet it. |
The third one is worth dwelling on, because it runs both ways. Filed as an AA failure it spends budget that did not have to be spent. Left off the report entirely it hides a real usability problem your keyboard users hit every day. The honest treatment is to write it up, say plainly that it passes at AA, and let somebody decide whether to fix it anyway. A report that only contains conformance failures is a smaller document than the one a team actually needs.
And one barrier can breach two rules at once. A div with an onclick handler, no role and no name, has no accessible name or role, which is 4.1.2, and cannot be reached from the keyboard, which is 2.1.1. Both are Level A. File it under one and you have under-counted the report and, worse, you have written half a fix. Our own sample report carries that finding with both numbers on it, for exactly this reason.
What the Severity Field Is Doing There
Severity is useful and it is not the standard's. WCAG has no severity scale, no score and no rating scheme, and W3C says so plainly while explaining why it has never published one. So a severity band is a judgment made by whoever wrote the report, which makes it worth having and worth labeling.
You can see the problem in how little agreement there is. US federal reporting guidance names Critical, High, Moderate or Medium, and Low. The engine behind most free scanners types its impact as critical, serious, moderate and minor. Our own audit report template uses Blocker, Serious, Moderate and Minor, and our sample report renders two chips, Critical and Serious. Four vocabularies, three of them ours or in our own delivery path, and no two the same.
That is fine, as long as the report defines its bands and grades them by what happens to a person rather than by the rule's level. A Level A failure on a page nobody visits and a Level AA failure in your checkout are not the same problem, and the level cannot tell you which is which. What the band must never do is travel upward as though a standard produced it. Our guide to reading an audit report works through severity, level and effort as three separate questions, which is the version to hand a stakeholder.
Acceptance Criteria Are Not the Remedy Written Twice
The remedy says what to change. The acceptance test says what somebody observes afterwards, and the whole value is that it can be run by a person who did not write the code. Get in the habit of writing it in the second person and in the present tense, because that forces it into an observation rather than an intention.
- Name the pairing. With VoiceOver on Safari is part of the test, not a footnote, because the failure was found on a combination and the fix has to be confirmed on one.
- Say what is heard or seen, in words. The announcement contains the field name and the error text is checkable. The error is announced properly is not.
- Include the state. If the failure only exists after a submit, a validation error, an expanded menu or a timeout, the test has to reach that state or it tests nothing.
- Add the negative case where one exists. And the message is not read twice catches the commonest regression in the whole category, which is the fix that lands twice.
That last bullet is not theoretical. A team told a message goes unannounced will often add a live region and move focus to the message in the same change, because both look like diligence. Moving focus is a change of context, and a status message is defined as a change in content that is not a change of context, so the live region was never the right instrument once focus moved. Now the message announces twice and the second reading interrupts the first. It looks correct in the diff. Our guide to what counts as a change of context has the definition that settles it.
The Regression Test That Stops It Coming Back
An acceptance test proves the fix landed once. A regression test proves it is still landed in March. They are different artifacts and only one of them survives the sprint, so decide which findings deserve the second one and write it while the first is fresh.
Three of them are worth the effort, and the rest usually are not. Anything a linter or a unit test can assert, so a missing alt attribute, an empty accessible name, a duplicate landmark with no label, belongs in the build where it costs nothing to run forever. Anything that lives in a shared component belongs in that component's own test, because the component is where the fix actually happened. And anything on a revenue journey belongs in whatever end-to-end suite you already run, as a keyboard-only path rather than a click-through, because a mouse-driven test walks straight past the failure. Our guide to accessibility checks in CI covers the machinery.
Everything else gets a line in your definition of done instead, which is cheaper and honest about what it is. A checklist is not a test. It is a reminder attached to the moment somebody could still act on it, and for the judgment calls that no tool reaches, a reminder is the only mechanism there is.
One Finding Is a Worked Example, Not an Inventory
This is the trap that turns a good report into a bad fix round, and it is a matter of reporting convention rather than anybody cutting corners. W3C's evaluation methodology sets the default granularity of a report at one example for each criterion not met, and adds that it is good practice to flag issues that occur repeatedly. Listing every failure occurrence on every page is something the commissioner asks for, in the brief, before the work starts.
So a report saying 23 findings is not saying there are 23 broken things on your site. It is saying there are 23 kinds of broken thing, at least, with one specimen of each written up. A team that works only the listed elements ships a fix that misses the siblings, and the next audit finds the same rule failing on the pages nobody named.
Two ways out, and you want one of them. Ask for occurrence-level listing when you write the brief and pay for the transcription. Or accept specimen-level reporting and make every ticket start with a search, so the fix is scoped by the pattern rather than by the example. The second is usually the better buy on a templated site, because the search is fast and the answer is the template. Reading an audit report covers grouping findings by cause before any of them get assigned, which is the same move one step earlier.
Your Issue Tracker Is Not the Conformance Record
Once the findings are tickets, the board starts to feel like the truth. It is not, and the distinction matters the first time somebody outside your company asks what your site does.
A board records work. It records who picked something up, what they thought they did, and when they pressed the button that moved the card. It carries no evidence, it is edited by the people being measured, and a closed ticket is a claim by the person who closed it. The report is the record, because it is dated, it names its conditions, and it holds the screenshots. A retest is what turns a column of closed cards back into a record, which is a separate piece of work with its own document.
Keep the two joined by putting the finding reference in the ticket title and the ticket link in nothing at all. Findings flow one way. WR-014 appears on the board, so anybody can walk from a card back to the evidence, and nobody has to trust the board to know what was actually true on the day it was tested.
The ten-second test for any finding
Read one finding and ask whether you could hand it to a contractor who has never seen your site and get the right change back. If the answer is no, the missing piece is nearly always one of three things. Nobody said which state the page was in, nobody named the browser and screen reader, or nobody wrote down what fixed is supposed to look like. All three are cheap to add while the tester is still looking at the page, and expensive to reconstruct afterwards.
How to Ask for This Before the Work Starts
Every item above is a scoping decision rather than a favor, and each one costs less to agree in a brief than to chase in an email. Four sentences do it.
- Say who reads the report. A document written for a product manager and a document written for a developer are not the same document, and a supplier who knows which one you want will write it.
- Ask for reproduction steps that name the pairing. Browser, screen reader, versions, and the actions that reach the state. Without them a finding is a description rather than a defect.
- Ask whether findings are listed per occurrence or per criterion. Either is legitimate. Not knowing which one you got is what breaks the fix round.
- Ask what format the findings arrive in. If you want them in your tracker, say which tracker, because the transcription is where detail falls out and it is the easiest part of the job to do once, properly.
We wrote all four into the way our reports come out, and you can read the sample report before you spend anything to see whether we mean it. If your team would rather import than retype, the developer ticket pack is the same findings as issues your board already understands, and its own honest limit says plainly that it is careful transcription rather than new testing.