Commit Graph

8 Commits

Author SHA1 Message Date
Denis Defolie 91dcd7e07a Fix sentence correction rejecting valid answers over incidental text differences
AnswerValidator.validate_sentence_correction compared the typed
correction to the expected word with raw string equality, with none
of the tolerance already built for dictations: no case folding, no
typographic-apostrophe or whitespace normalization, no decomposed-
accent handling. Tapping "petit" and typing "petits" could fail for
reasons having nothing to do with the grammar point being tested
(e.g. a stray capital from autocapitalization), which violates the
"an ambiguous answer is never auto-marked wrong" invariant.

Found this while chasing a manual bug report: an automated test
reproducing the user's exact click sequence (tap once, type, submit)
did NOT reproduce the failure, which actually pointed at the real
gap -- the logic worked for byte-identical input, but had zero
tolerance for anything else. Now reuses TextNormalizer (built for
dictation analysis) before comparing, case-insensitively, while still
showing the child's raw typed text in the feedback. Three new tests
cover case, incidental whitespace, and decomposed accents.

Rebuilt both exports so the shipped binaries include the fix.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-11 18:12:56 +02:00
Denis Defolie 19831807b0 Wire up Linux and Windows exports
export_presets.cfg is hand-written (no editor GUI available here): a
minimal preset per platform (name, platform, path, x86_64
architecture) is enough, since Godot fills every other option from
its platform defaults. tools/setup.sh now also fetches the matching
export templates (~1.2GB, cached outside the repo like the Godot
binary itself) -- note the directory it unpacks into uses a dot
before "stable" while .godot-version and the download URLs use a
hyphen, two different spellings of the same version that are easy to
conflate.

Both make export-linux and make export-windows now actually run and
produce a working package; tests/ and addons/gut/ are excluded from
the exported .pck (124KB vs 1.5MB before -- a dev-only dependency has
no business shipping to a child's machine). The Linux binary was
smoke-tested headless and boots cleanly; the Windows .exe could only
be confirmed as a valid PE32+ binary, since no Windows machine or
Wine is available in this environment -- flagged in
docs/testing/manual-checklist.md rather than claimed as verified.

This closes out every step in the launch prompt's "Ordre de
construction." README status lines updated to reflect the first
playable prototype rather than a bare skeleton.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-11 17:46:34 +02:00
Denis Defolie 493a8617d7 Add the playable scene loop: boot through mission to reward
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>
2026-10-11 17:37:37 +02:00
Denis Defolie ebabe91821 Add profile and save persistence, wired into the three autoloads
scripts/profiles/: SaveIO handles real file I/O in user://saves (one
file per profile_id, atomic write via temp-file-then-rename, backup
copy before each overwrite, corrupted-main falls back to backup,
schema-invalid content is rejected like corruption). SaveMigration
and SaveFactory are pure; SaveMigration refuses a schema_version it
doesn't recognize (older or newer) rather than guessing. ProgressUpdates
is pure and wires ReviewScheduler/DifficultyManager onto a save's
skills dict, including per-session overdue-review marking.

The three autoloads (SaveManager, ProfileManager, ProgressManager)
stay thin: in-memory current-profile state and orchestration only,
no logic of their own, so the actual behavior lives in the tested
pure/file-IO modules above rather than in untestable glue.

26 new headless tests, including the failure modes called out in the
launch prompt: a truncated .tmp file never corrupts the readable
save, a corrupted main file falls back to its backup, two profiles
never mix (down through the real autoload layer, not just SaveIO),
and an unknown future schema_version is rejected outright.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-11 17:12:50 +02:00
Denis Defolie 2fe455f5d1 Add pure correction and pedagogy logic with full test coverage
scripts/correction/: AnswerValidator (multiple choice, sentence
correction via tap-the-faulty-word + retype) and DictationAnalyzer
build the CorrectionResult structure from cahier des charges §6.
Dictation analysis aligns words with WordAligner (Wagner-Fischer edit
distance) before any character comparison, so an omitted or added
word doesn't cascade into false errors on every following word.
TextNormalizer handles non-breaking spaces, typographic apostrophes,
and decomposed-vs-composed French accented characters via an
explicit table (GDScript has no built-in NFC/NFD normalization).
Error classification follows the data annotations only (rule_id
present -> grammatical, absent -> unclassified), never a runtime
linguistic guess.

scripts/pedagogy/: DifficultyManager (per-skill difficulty from
recent results), AttemptFlow (3-attempt graduated aid: hint, then
explanation, then reveal, matching exercise-lifecycle.md's second
gap), and ReviewScheduler (the five mastery states from §9, with
session-counted spaced review intervals [1, 3, 6, 12] rather than
wall-clock dates, since a family device's clock isn't trustworthy).

All of it is pure: no scene tree, no clock or RNG read directly,
every effectful input (session number, attempt outcome) is a
parameter. 65 headless tests across both layers, including the
word-omission-doesn't-cascade regression and the full
decouverte -> acquise -> a_reviser -> acquise path.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-11 17:03:14 +02:00
Denis Defolie d057c8ee77 Add JSON schemas, data validator, and first CE1 content
Introduces a generic JSON-Schema-subset validator in GDScript
(scripts/data/schema_validator.gd) used both by `make validate-data`
and, later, by ExerciseEngine at load time, plus semantic_checks.gd
for cross-field constraints a schema can't express (answer index
bounds, at least one faulty token in sentence correction, word count
matching between a dictation's target_text and its annotations).

Schemas cover rule, exercise (dispatched per type: multiple_choice,
sentence_correction), dictation, curriculum, and save (save.schema.json
is not yet wired into validate-data; saves live in user://, handled
at the Profiles/Saves step).

First draft content for the CE1 "accord_adjectif" rule (one rule, two
multiple-choice exercises, one sentence correction, one dictation,
one curriculum entry) exercises the full pipeline end to end and
seeds docs/review/content-review.md, regenerated by the new
tools/generate_content_review.py (`make content-review`).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-11 16:47:28 +02:00
Denis Defolie a1f749de40 Add project skeleton: Godot setup, tooling, and smoke test
Pins Godot 4.6.3-stable and GUT 9.6.0 (9.6.1+ reference
AccessibilityServer, unavailable in 4.6.3) via tools/setup.sh. Wires
make check (gdlint + gdformat config for 4-space indent, headless
GUT run, and a JSON well-formedness check ahead of real schema
validation). Seven autoload stubs match the architecture in the
cahier des charges; real logic lands with the following steps.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-11 16:15:19 +02:00
Denis Defolie 50198a49a2 Add project specs, stage-0 decisions, and AGPL-3.0 license
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-11 16:06:51 +02:00