Skip to content

Wire up repair drills, and let the drill surface be heard repeating itself - #23

Merged
RCheesley merged 3 commits into
mainfrom
finish-v1
Sep 23, 2026
Merged

RCheesley merged 3 commits into
mainfrom
finish-v1

Conversation

@RCheesley

Copy link
Copy Markdown
Owner

Stacked on #22 — its base is sprint-mode, so GitHub retargets this to main when you merge that. Merge #22 first.

Three loose ends, all in drill-view.ts and load-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.

  • The offer is made only when something is wired up to honour it — the same rule advancing follows. 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 the weak-key report reads.
  • It carries no next lesson: 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 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 announceInto but 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.ts is now exported from the drill barrel like the rest of its layer, and the sprint text helpers move into tests/e2e/helpers.ts instead of living twice in two spec files.

Verified by hand, not only by test

A lesson fumbled on t offered Repair drill · T, and the repair read:

fast nta at tan data idti sit ditst fast fast

Every character inside lesson one's key set, t eleven 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 todo left in the regression suite.

One journey outstanding: announces the current word and the result, but not every keystroke. It stays fixme because no test can answer it. See #10 and docs/screen-reader-testing.md.

🤖 Generated with Claude Code

RCheesley and others added 2 commits September 22, 2026 19:12
…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>
Base automatically changed from sprint-mode to main September 23, 2026 08:55
@RCheesley
RCheesley merged commit 8ec7c13 into main Sep 23, 2026
3 checks passed
@RCheesley
RCheesley deleted the finish-v1 branch September 23, 2026 09:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant