I build Pianory, a browser-based piano learning app. AI helped draft this article; I checked the behavior against the current implementation and its focused tests.
A course step can be hard without being finished or abandoned. Our course journey models that case with a recovery branch attached to the original step. The important invariant is that help changes the active activity, while the learner's step identity remains stable.
The branch is deliberately narrow. A partial attempt with a self-report rating of stuck can enter recovery only when the authored step has a recovery path and the cursor is in the original or retest phase. A failed quiz alone does not trigger it. When the condition matches, the enrollment cursor keeps its stepId and preset, adds the recovery branchId , and changes phase to explanation .
courseActiveStep resolves the explanation phase to an authored lesson and the drill phase to an authored drill. Both are temporary activities under the original step.…