Manual test: the Piper voice (previous commit) is now intelligible,
but typing exactly what's heard ("Les petits chats dorment", no
period) was rejected. The provisional audio never vocalizes
punctuation, so nothing tells the child to add it — penalizing its
absence punishes information they were never given.
DictationAnalyzer now strips terminal punctuation (. ! ? …) from both
sides before comparing, in the exact-match/variant check and before
word alignment, without touching punctuation elsewhere in the
sentence. A real error on the last word is still caught (added test).
A scene-level test reproducing the exact reported interaction
(tests/exercises/test_exercise_host_dictation.gd) failed before the
fix and passes after.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Manual report: after "Bravo!", clicking Continue seemed to do
nothing. An automated test proved the mission does advance (a new
exercise instance loads, completed_count increments) -- but
mission_02_pont_des_phrases has exactly one sentence_correction
exercise in the data right now, so the "next" exercise is the
identical sentence the child just solved. Nothing was broken; there
was just no visible signal that progress happened.
Added a persistent progress label at the top of exercise_host,
updated on every exercise load. Doesn't address the underlying
content-volume gap (still tracked in decisions.md point 14), but
makes the repetition legible instead of indistinguishable from a
stall.
Rebuilt both exports.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Investigating a manual bug report ("typing petits as the correction
for petit doesn't validate"): both a direct test of
sentence_correction.tscn and a full exercise_host integration test
(mission_02_pont_des_phrases) tap the faulty token, type its exact
expected correction, and submit -- both pass, confirming the
validator and the scene wiring correctly accept "petits" when the
word is tapped once and the correction is typed before pressing
Valider.
Caught along the way: a first draft of the direct-scene test used a
lambda connected to answer_submitted to capture its parameters into
outer local variables -- GDScript closures capture locals by value
at creation time, so reassigning them inside the lambda never
reaches the outer scope. Switched to GUT's
assert_signal_emitted_with_parameters, the supported way to inspect
signal arguments in a test.
No fix applied yet: these tests confirm the intended interaction
works, but don't rule out a real fragility noticed while reading the
code -- toggling a token off deletes its LineEdit (and whatever was
typed in it) immediately, so an accidental second tap on the same
word silently discards the correction. Needs the user's exact click
sequence to confirm before changing behavior.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Wires every autoload up to a real UI: boot -> profile select/create
-> world map (three mission markers, positioned from data, not
hardcoded pixels) -> mission intro (narrative from data/missions/,
a new data type with its own schema) -> rule panel -> exercise host
-> one of the three exercise type scenes -> feedback panel -> reward
screen -> back to the map.
exercise_host is the only piece with real orchestration logic: picks
exercises via ExerciseEngine (now fully implemented, validating at
load like make validate-data does), validates answers through the
pure AnswerValidator/DictationAnalyzer, escalates aid over 3 attempts
via AttemptFlow, feeds DifficultyManager so adaptive difficulty is
actually wired in rather than dead code, and records every attempt
through ProgressManager. Every exercise-type scene (multiple_choice,
sentence_correction, dictation) only emits its answer by signal, per
the architecture invariant.
All child-facing text now comes from data/localization/fr.json via
UIText, not hardcoded in scripts or scenes. Getting that right
required extending SchemaValidator to support "additionalProperties"
as a schema (dynamic keys), which also closed a real gap: save.skills
was previously unvalidated against SkillState's actual shape.
16 new headless tests, including two integration tests that instance
exercise_host.tscn directly and drive it by emitting child-scene
signals, stopping short of the final scene transition (which would
tear down the test runner's own tree). Everything that needs a
screen -- layout at different sizes, touch, virtual keyboard, actual
audio playback (no .ogg files exist yet) -- is listed in the new
docs/testing/manual-checklist.md instead of claimed as verified.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>