feat(learning): persist roadmap progression locally without an account#66
Merged
Conversation
Derssa
approved these changes
Jul 17, 2026
OthmaneZ05
added a commit
that referenced
this pull request
Jul 18, 2026
#66) * feat(learning): persist roadmap progression locally without an account * docs(learning): document the local progression store and its endpoints
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.
Summary of Changes
A roadmap is played across several sessions, but until now every player state died with the page: reloading meant starting from step 1. This PR persists roadmap progression locally — completed steps, validation attempts and revealed hints — with zero account and zero auth, so reopening a roadmap resumes exactly where the learner left off, even after fully restarting the app.
~/.torollo/progress.json, next toprojects.json): newProgressService— versioned envelope (version: 1), one entry per(projectId, roadmapId), per-step data keyed by stable step ids (reordering/re-editing a roadmap file can't corrupt progress; translations share progress). Write-then-rename so a crash can't truncate the file. A corrupt or unknown-version store is moved aside asprogress.json.corrupt, the app starts fresh, and the UI tells the user (one-shotstoreRecoveredflag) — never a crash, never silent.POST /validatenow records the attempt + latest verdict at the API layer (the engine stays stateless; a storage failure is logged and never blocks the verdict). Hint reveals are pushed by the player as absolute counts (fire-and-forget, self-healing). New endpoints:GET/PUT …/hints/DELETEunder/api/learning/progress/:projectId/:roadmapId.Contract documented in
docs/learning-api.md(store format = the future migration contract).Types of Changes
Verification & Testing
Automated Checks
npm run lintsuccessfully with no errorsnpm run buildsuccessfully with no compilation errorsnpm testsuccessfully (all tests pass)Backend: 237 tests (20 new —
ProgressServiceround-trips on real tmp files incl. corruption/unknown-version recovery and reset scoping; controller contract incl. "recording failure never blocks the verdict"). Frontend: 225 tests (12 new — hydration, first-incomplete-step resume, hint push, reset, recovery notice). Note: a few heavy pre-existing modal/canvas tests sit close to their 5s timeout and can flake under parallel load on a busy machine (seen onmainfiles untouched by this PR, e.g.PostgresModal/NoSqlModal/CanvasPage); they pass consistently when the machine isn't saturated.Manual Verification
Full kill & restart scenario against real Docker (Playwright + Chrome, example roadmap):
web+dbcontainers, seededuserstable), revealed step 3's hint.progress.jsonholds the exact attempts/verdicts.progress.json→ app opens normally, amber notice shown once and dismissible, original file kept asprogress.json.corrupt, next validation recreates a fresh store.Checklist