Add expert level to The Accessibility Nightmare - #94
Merged
sinduri-g merged 8 commits intoSep 23, 2026
Merged
Conversation
The Compliance Engine asks why a gate that has been green for months never caught the barrier the company is being audited over. The answer is in two parts: it only ever scanned one of the four pages a customer passes through, and the fault it was meant to find is behavioural, so no amount of scanning would have reached it. Players extend scanner coverage, discover that doing so finds nothing, diagnose the silence with a virtual screen reader, repair the routing, and produce a compliance report that records what each check proved. Verification plants a fault on the payment page and requires the scan to go red, so coverage is measured rather than assumed — a suite that stays green never opened that page. Adds check_playwright_tests_detect to lib/scripts/node.sh, which asserts a tagged suite fails. Purely additive; no existing caller changes. Also removes the rewards block from the adventure index, as the adventure has no rewards. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: sindurigf <sinduri.g@gmail.com>
Check 3 plants a fault in the payment page and requires the player's scan to catch it. Three ways that could go wrong: The recovery that undoes a crashed probe lived inside the branch taken only when the scan was already green, so a run killed mid-probe left the planted fault in place and then failed check 2 — for exactly the player who had widened their scan to reach that page. Recovery now runs before any check, and self-heals. The trap was armed before the backup was known good, so a short write could leave a truncated backup that the handler then moved over the original. The backup is now compared byte for byte before it is relied on, and the handler chains loader.sh's own cleanup rather than replacing it. The inverted check treated any non-zero exit as "fault caught", so Ctrl-C scored a pass and the run carried on. Only exit code 1, a real test failure, counts now; anything else reports that the check could not be measured. Also: drop the python3 dependency the prerequisite check never declared, resolve the report path against the vite server root rather than cwd, read test outcomes after retries rather than from the first attempt, ignore the probe backup, add set -e to the devcontainer scripts to match the sibling levels, and stop pointing players at a localhost URL that does not resolve in a Codespace. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: sindurigf <sinduri.g@gmail.com>
A cold read of the docs and the reference page found the defect identifiable before the player ran anything, which leaves objective 2 with nothing to find. The reference table paired "the document has a title" with "route change announces the new page" as two halves of one criterion, and highlighted both. That was the sharpest statement of the lesson and also the answer, printed before any investigation. The row is now the fault class rather than this app's instance of it, and the highlight is gone. The WCAG links named the two criteria outright; they now point at the guideline and at the quick reference, so the player still has somewhere to look but has to work out which criterion their tests verify. Two smaller tells removed: the listen-panel instructions said to read what does not arrive after the marker, and the @transition hint said to watch what arrives after the address changes. Both named the conclusion. They now describe how to read the panel and leave the judgement open. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: sindurigf <sinduri.g@gmail.com>
The route marker was printed after awaiting a drain. That await yields the event loop, React commits its re-render, and the new page's announcement reaches the log in time to be flushed above the marker it belongs below — so the panel showed the arrival before the navigation that caused it. The marker is now queued on hashchange and printed at the end of the drain that call kicks off. React commits after the handler returns, so that drain still reads a log ending at the previous page: phrases spoken before the navigation land above the marker, the arrival lands below it. Overlapping drains are also blocked. Two calls could both slice from the same index and print the same phrases twice, which the 200ms poll made likely during navigation. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: sindurigf <sinduri.g@gmail.com>
The level could be passed by announcing a fixed string. That satisfies a naive "something was announced" assertion and is broken twice over: it never tells the customer which page they reached, and because the text never changes there is no mutation for the browser to announce, so it goes silent from the second navigation onward. Announcing assertively passed too, though it interrupts whatever the user was listening to. A new check drives the repaired storefront directly rather than trusting the player's own tests, which prove only what the player chose to assert. It moves between two pages in a row and requires each arrival to be announced, the two to differ, and neither to interrupt. Verified to discriminate: unfixed fails, a fixed string fails, an assertive live region fails, naming the destination politely passes. An over-announcing check was tried first and dropped. React bails out when the text is unchanged, so a missing dependency array produced no extra announcement and the test would have passed for everyone. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: sindurigf <sinduri.g@gmail.com>
A tone pass against beginner and intermediate, which set the house
voice. Removed the consultancy phrasing ("which tool bridges the gap"),
the unearned adjective on axe-core, the benefit claim about a report
that "stands up to audit", and two lines that graded the player's work
before they had done any.
Cut "that is the lesson, not a bug", which congratulated the challenge
on its own twist and pre-empted the one thing the player is meant to
notice for themselves. Deleted a duplicated instruction to assert the
outcome rather than the mechanism, which appeared twice within four
lines.
Added the storefront opener both siblings carry and this level was
missing: where the Ports tab is, that Codespaces serves from
.app.github.dev with no localhost to visit, and how to start the server
by hand. The level referenced that tab without ever introducing it.
Dropped the status-politeness binding from the coverage reference. No
doc, hint or spec ever asked for that annotation, so the row was
permanently unsatisfiable; politeness is enforced by the new check
instead. Also stopped one verify hint from restating the annotation type
the docs already give.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: sindurigf <sinduri.g@gmail.com>
The coverage hint opened with "Something is announced, but...", which is false in the state every player meets first: nothing is announced at all. It now describes what the two arrivals have to do, which reads correctly whether the player has heard silence, a fixed string, or an announcement that interrupts. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: sindurigf <sinduri.g@gmail.com>
Checks 2 to 4 reach the storefront through playwright.config.js, which starts the server if it is not already up. Check 5 drives the page itself, so nothing starts it — and a dead port produced the hint about an announcement that does not survive a second navigation, sending the player to debug a fix that was never the problem. It now probes the port first and says so. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: sindurigf <sinduri.g@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The Compliance Engine asks why a gate that has been green for months never caught the barrier the company is being audited over. The answer is in two parts: it only ever scanned one of the four pages a customer passes through, and the fault it was meant to find is behavioural, so no amount of scanning would have reached it.
Players extend scanner coverage, discover that doing so finds nothing, diagnose the silence with a virtual screen reader, repair the routing, and produce a compliance report that records what each check proved.
Verification plants a fault on the payment page and requires the scan to go red, so coverage is measured rather than assumed — a suite that stays green never opened that page.
Adds check_playwright_tests_detect to lib/scripts/node.sh, which asserts a tagged suite fails. Purely additive; no existing caller changes.
Also removes the rewards block from the adventure index, as the adventure has no rewards.
What does this PR do?
Closes #
Type of PR
💡 Adventure Idea
ideas/(notideas/.implemented/)🗺️ New Adventure Level
verify.shpasses when the challenge is solvedverify.shfails with helpful error messages when not solvedideas/.implemented/(first level PR only)Part of #for earlier levels,Closes #for the last one)📖 Solution Walkthrough
adventures/XX-.../docs/solutions/level.md)📝 Other