Conversation
…tself Three loose ends, all in the same file, so one change. Repair drills existed as a module with nothing calling them. The result card already worked out which keys slipped; it now offers a drill built from exactly those and builds it on the lesson they slipped in. The offer is made only when something is wired up to honour it, the same rule advancing follows, because a button naming a thing it will not do is worse than one offering another go. A repair carries the lesson's id so its keys feed the same statistics, and no next lesson, because a repair is not a rung and nobody should climb the ladder by fumbling. generateRepairText throws on a key the lesson cannot type; that throw is surfaced, never turned back into an ordinary drill. The drill surface now announces through announceInto. A live region speaks only when its contents change, so mistyping the same key twice in a row was announced once — and the drill surface is where that happens. Two tidies the sprint work could not reach from inside its own file list: sprint.ts is exported from the drill barrel like the rest of its layer, and the sprint text helpers move into tests/e2e/helpers.ts instead of being duplicated in two spec files. Fills in the repair-drill journey, which needed the wiring to exist. That leaves every one of the eight shipped regressions asserted and one journey outstanding: whether a screen reader announces the right things, which no test can answer. Verified by hand as well as by test: a lesson fumbled on "t" offered a repair, and the repair read "fast nta at tan data idti sit ditst fast fast" — every character inside the lesson's key set, "t" eleven times, never doubled. A timed sprint abandoned mid-drill left the following lesson able to run all sixty characters to three stars, which is the failure this project started with. Co-Authored-By: Claude Opus 5 <noreply@anthropic.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.
Stacked on #22 — its base is
sprint-mode, so GitHub retargets this tomainwhen you merge that. Merge #22 first.Three loose ends, all in
drill-view.tsandload-form.ts, so one change rather than three conflicting ones.Repair drills were built but never called
#21 landed the module; nothing invoked it. The result card already worked out which keys slipped, so it now offers a drill built from exactly those.
generateRepairTextthrows on a key the lesson cannot type. That throw is surfaced, never caught and turned back into an ordinary drill — Build repair drills from exactly the keys that slipped #21's agent flagged that trap explicitly and it would have been easy to fall into.The drill surface can now be heard repeating itself
#20 added
announceIntobut only reached the progress views. A live region speaks only when its contents change, so mistyping the same key twice in a row announced once — and the drill surface is exactly where that happens.Two tidies the sprint work could not reach
Both flagged by #22's agent as outside its own file list:
sprint.tsis now exported from the drill barrel like the rest of its layer, and the sprint text helpers move intotests/e2e/helpers.tsinstead of living twice in two spec files.Verified by hand, not only by test
A lesson fumbled on
tofferedRepair drill · T, and the repair read:Every character inside lesson one's key set,
televen times, never doubled — #21's never-adjacent rule holding in practice rather than only in its unit test.And the one that matters: a timed sprint started, typed into, then abandoned mid-drill by choosing a lesson from the ladder. The lesson then ran all sixty characters to three stars with no stale countdown inherited. That is the failure this project started with.
Where this leaves version one
566 tests, 144 end-to-end, and all eight shipped regressions asserted — zero
todoleft in the regression suite.One journey outstanding: announces the current word and the result, but not every keystroke. It stays
fixmebecause no test can answer it. See #10 anddocs/screen-reader-testing.md.🤖 Generated with Claude Code