The recorded run is the saved evidence. The numbers below come from the local CLI run of 27 October 2026, with the full Playwright trail. You can also run a fresh Beam repair from this page through a server-side proxy, or open the bundled two-page demo. Those runs are verified in your browser and do not change the recorded result. The interactive app still runs locally with Node.js and Chromium.
Verified accessibility repair
Six findings in. Zero out. Every edit checked.
Patchproof sent two HTML pages and their axe-core findings to Beam. Beam returned exact search/replace edits. Playwright applied them to a copy and rescanned it, and the copy kept only the edits that measurably removed findings without adding new ones.
Run a fresh Beam repair
Choose one HTML file to repair, or review the recorded five-mode benchmark and run the bundled demo at a chosen effort. Axe-core runs in this tab. A candidate is kept only if the rescanned copy removes targeted findings without adding new ones. The Reflection key stays in the server-side proxy and is never sent to the browser.
Upload one complete .html file. Scripts, iframes, event handlers, script
URLs, and meta refreshes are removed before scanning. Only the sanitized HTML and its
findings for html-has-lang, button-name, and
label are sent through the proxy to Beam.
The uploaded page gets at most two Beam attempts. A rejected candidate is sent back to Beam with the deterministic failure message. The sanitized copy is retained if both attempts fail. The proxy rate-limits requests per network to slow abuse.
Recorded comparison
Five reasoning efforts, measured
All five efforts ran the same two-page fixture through the CLI on 28 October 2026, one attempt per page. Playwright and axe-core verified every candidate. All five repaired both pages. This is a single combined evidence file, not a live five-mode run, so it adds no Beam calls when you read it.
| Effort | Pages repaired | Targeted | Total tokens | Prompt | Completion | Reasoning | Elapsed | Requests |
|---|---|---|---|---|---|---|---|---|
| Low | 2 / 2 | 6 → 0 | 3,767 | 2,990 | 777 | 362 | 11.2 s | 2 |
| Medium | 2 / 2 | 6 → 0 | 4,104 | 2,992 | 1,112 | 737 | 9.6 s | 2 |
| High | 2 / 2 | 6 → 0 | 4,413 | 2,994 | 1,419 | 1,013 | 11.2 s | 2 |
| X-high | 2 / 2 | 6 → 0 | 4,628 | 2,994 | 1,634 | 1,224 | 11.7 s | 2 |
| Max | 2 / 2 | 6 → 0 | 4,719 | 2,994 | 1,725 | 1,314 | 13.6 s | 2 |
Elapsed time is the CLI wall clock for each mode, including Playwright scans. Low was slower than medium in this sample; that is run-to-run variance, not a monotonic latency curve. Token counts increase with effort.
Run the bundled demo
A single run makes up to four Beam requests, two pages with at most two attempts each. The demo sends only the fixed page name, the selected effort, and, on a retry, the rejection message. The recorded CLI run above remains the primary evidence.
The recorded result
Counts come from Playwright and axe-core before and after the accepted edits.
Targeted findings
6 → 0
All violation nodes
6 → 0
Pages repaired
2 / 2
Elapsed
55.6 s
Tokens
4,105
| Page | Outcome | Targeted | Rules before | Rules after | Beam attempts |
|---|---|---|---|---|---|
| index.html | Repaired | 3 → 0 | button-name: 2 · html-has-lang: 1 |
None | 1 of 2 |
| contact.html | Repaired | 3 → 0 | html-has-lang: 1 · label: 2 |
None | 1 of 2 |
“Repaired” means the candidate passed the acceptance rule: the targeted count decreased, the total did not increase, no new rule appeared, and no existing rule increased. It does not mean the page is fully accessible.
The fixture, before and after
Printworks Studio is bundled demo data, not a real organization.
Screenshots of the saved fixture and the accepted copy. The layout barely changes; the accessibility repair is in the HTML source shown below. Form submissions are not part of the fixture.
What Beam changed
Six accepted edits. Each one is an exact string match applied once.
index.html — 3 edits
-
html-has-lang
<html>became<html lang="en">. -
button-name
The search button gained
aria-label="Search". -
button-name
The clear button gained
aria-label="Clear search".
contact.html — 3 edits
-
html-has-lang
<html>became<html lang="en">. -
label
Added
<label for="email">Email</label>. -
label
Added
<label for="message">Message</label>.
Beam proposed the edits; application code validated the response, found each
find string exactly once, applied it to a fresh copy, and rescanned.
The original fixture was never edited.
Accepted changes
The exact unified diff saved with the run.
===================================================================
--- a/index.html
+++ b/index.html
@@ -1,6 +1,6 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Printworks Studio — Home</title>
@@ -30,10 +30,10 @@
<form class="search-form" action="index.html" method="get" role="search" aria-labelledby="search-heading">
<label for="search-query">Search our print catalogue</label>
<div class="search-controls">
<input id="search-query" name="q" type="search">
- <button type="submit" id="search-button"><span aria-hidden="true">🔍</span></button>
- <button type="reset" id="clear-button"><span aria-hidden="true">×</span></button>
+ <button type="submit" id="search-button" aria-label="Search"><span aria-hidden="true">🔍</span></button>
+ <button type="reset" id="clear-button" aria-label="Clear search"><span aria-hidden="true">×</span></button>
</div>
</form>
</section>
===================================================================
--- a/contact.html
+++ b/contact.html
@@ -1,6 +1,6 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Contact — Printworks Studio</title>
@@ -28,12 +28,14 @@
<h2 id="form-heading">Send a message</h2>
<form class="contact-form" action="contact.html" method="post">
<div class="field">
<p class="field-hint" id="email-hint">We only use this to reply.</p>
+ <label for="email">Email</label>
<input id="email" name="email" type="email" autocomplete="email">
</div>
<div class="field">
<p class="field-hint" id="message-hint">Include format, quantity, and timing if you can.</p>
+ <label for="message">Message</label>
<textarea id="message" name="message" rows="6"></textarea>
</div>
<button class="primary-button" type="submit">Send message</button>
</form>
Diff and patch are also available as changes.patch.
Verification trail
Request IDs, finish reasons, and token usage recorded by the CLI.
Beam attempts
index.html — repaired, 1 attempt
-
Attempt 1: accepted
Rescan: 3 targeted → 0; 3 total → 0; no validation or rejection errors.
contact.html — repaired, 1 attempt
-
Attempt 1: accepted
Rescan: 3 targeted → 0; 3 total → 0; no validation or rejection errors.
Aggregate usage: 2,946 prompt · 1,159 completion · 734 reasoning · 4,105 total. The maximum is two attempts per page.
Saved run artifacts
- report.json Full scans, page outcomes, edits, request IDs, usage, and limitations.
- changes.patch The unified diff between the fixture and the repaired copy.
- patchproof-a11y-source.zip Source code, tests, fixture, and the recorded run.
- Repaired index.html The accepted copy, opened directly.
- Repaired contact.html The accepted copy, opened directly.
No residual findings were reported for either page in this run. The report’s own limitation statement still applies.
Run it yourself
The same repairSite pipeline backs the CLI and the local web demo.
CLI
npm ci
npx playwright install chromium
$env:REFLECTION_API_KEY = "<your Reflection key>"
npm run scan -- ./fixtures/demo-site
npm run fix -- ./fixtures/demo-site
Local web demo
npm run build
npm start
# open http://localhost:7860
The server accepts no URLs, uploads, prompts, or visitor HTML. It only repairs the bundled fixture, serializes requests, and serves the latest run.
The Reflection API key stays in the server process. It is never sent to the browser or
written to report.json. The hosted live runner uses the Cloudflare Worker
proxy in worker/ for the same reason; the static page performs network
requests only when you press Run live Beam repair.
What this result does not prove
Automated checks with axe-core cover only a subset of accessibility requirements. They do not establish full WCAG compliance. Manual review by people with disabilities is still required.
- Only
index.htmlandcontact.htmlwere scanned. - Only
html-has-lang,button-name, andlabelwere targeted. - CSS, JavaScript, focus order, reading experience, and content quality are outside this demo.
- The recorded run is a saved artifact. The live runner performs a fresh, rate-limited repair with one browser-side axe-core pass per candidate; the recorded CLI run remains the stronger evidence because it used Playwright on served copies.