Skip to content

feat(terminal): start each lesson from the state it teaches (THI-353) - #385

Merged
thierryvm merged 1 commit into
mainfrom
feat/p1-lesson-setup-fidelity
Sep 23, 2026
Merged

thierryvm merged 1 commit into
mainfrom
feat/p1-lesson-setup-fidelity

Conversation

@thierryvm

@thierryvm thierryvm commented Sep 23, 2026 •

Copy link
Copy Markdown
Owner

Why

Refs THI-353 (P1 of the September check-up). Every lesson mounted a fresh default terminal, so the Git lessons asked for git status, git merge feature/x or git push -u origin main in a terminal with no repository, no branch and no remote. The learner typed exactly what the lesson said, got fatal: not a git repository in red, and the exercise still validated: validate() only reads the command string, never the engine output.

What

  • Exercise.setup (src/app/data/lessonSetup.ts): a pure transform of the initial state + a one-line note shown in the terminal welcome message. Git lessons start in ~/projets with the repository / branch / remote they need; the security lesson gets a simulated ~/.ssh with the 700/600/644 permissions it teaches.
  • TerminalEmulator.initialState: builder read once per mount (lesson change or « Réinitialiser »).
  • Output keeps its spacing (git branch indentation, git status tabs); long tokens still wrap (checked at 390px).
  • No raw markdown in the terminal welcome message, instruction, success message and hint (backticks / ** were shown literally).
  • Scripts lesson, Windows hint: now says cd projets first (found by the new drift check).

Permanent guard

src/test/lessonFidelity.test.ts replays, for every lesson × environment, the command the lesson tells the learner to type and requires it to validate and print no error line. lessonSolutions.ts must match the lesson instruction/hint word for word, so it cannot drift.

The 9 cases still broken in the engine (2>, ./script.sh, $PROFILE, three PowerShell cmdlets) run as it.fails in KNOWN_DESYNCS — a ratchet that can only shrink: fixing one turns the suite red until its entry is removed. They are the next PRs of THI-353.

before after
lesson × env validating with an error on screen (engine replay) 44 / 198 9 / 198
of which Git 33 0

Gates

  • curriculum-validator (before editing curriculum.ts): GO
  • test-runner: type-check ✅ lint ✅ vitest 2526 pass / 9 expected-fail / 0 fail
  • ui-auditor: PASS (1 warning applied: setup note stripped too)
  • feature-dev:code-reviewer: SHIP, no finding ≥ 80
  • build ✅ — bundle vs main: LessonPage +0.06 kB gzip, curriculum +0.7 kB gzip
  • Each new test verified red without its fix (TerminalEmulator stash → 3 red)
  • Chrome (dev server): git merge, git merge --no-ff, git remote, ls -la ~/.ssh validate with 0 red line; mobile 390×844 (CPU 4×): 0 horizontal overflow, 0 console error

🤖 Generated with Claude Code

Résumé par Sourcery

Démarrer chaque terminal d’exercice depuis l’état contextuel requis par sa leçon et ajouter des vérifications de régression pour garantir la fidélité des commandes et de leur sortie.

Nouvelles fonctionnalités :

  • Initialiser les terminaux des leçons avec des dépôts Git spécifiques au contexte et le contenu requis des répertoires SSH afin que les commandes s’exécutent dans l’état enseigné.

Corrections de bugs :

  • Empêcher les commandes Git et de sécurité recommandées par les leçons de produire des erreurs dans le terminal malgré la validation réussie de la commande.
  • S’assurer que la sortie du terminal conserve les espaces significatifs et renvoie correctement les jetons longs à la ligne.
  • Supprimer les marqueurs Markdown inline du texte d’accueil du terminal tout en affichant correctement les instructions, les indices et les messages de réussite des leçons.

Améliorations :

  • Ajouter un framework de fidélité des leçons qui rejoue chaque exercice dans les environnements pris en charge et suit les désynchronisations restantes du moteur.

Tests :

  • Ajouter une couverture pour l’immutabilité de la configuration des leçons, les états Git et SSH préparés, le comportement d’initialisation des terminaux, l’espacement de la sortie et la suppression du Markdown.
Original summary in English

Summary by Sourcery

Start each exercise terminal from the contextual state required by its lesson and add regression checks for command and output fidelity.

New Features:

  • Initialize lesson terminals with context-specific Git repositories and SSH directory contents so commands execute in the state being taught.

Bug Fixes:

  • Prevent lesson-recommended Git and security commands from producing terminal errors despite successful command validation.
  • Ensure terminal output preserves meaningful whitespace and wraps long tokens correctly.
  • Remove inline Markdown markers from terminal welcome text while rendering lesson instructions, hints, and success messages appropriately.

Enhancements:

  • Add a lesson-fidelity framework that replays every exercise across supported environments and tracks remaining engine desynchronizations.

Tests:

  • Add coverage for lesson setup immutability, prepared Git and SSH states, terminal initialization behavior, output spacing, and Markdown stripping.

Every lesson mounted a fresh default terminal, so the Git lessons asked for
`git status`, `git merge feature/x` or `git push -u origin main` in a
terminal that had no repository, no branch and no remote. The learner typed
exactly what the lesson said, got "fatal: not a git repository" in red, and
the exercise still validated: the validator only reads the command string.
The browser census of 23 September found 46 of 198 lesson x environment
combinations in that state; 33 of them were Git lessons.

- Exercise gains an optional `setup` (src/app/data/lessonSetup.ts): a pure
  function of the initial state plus a one-line note shown in the terminal
  welcome message. Git lessons start in ~/projets with the repository, branch
  or remote they need; the security lesson gets a simulated ~/.ssh with the
  700/600/644 permissions it teaches.
- TerminalEmulator takes an `initialState` builder, read once per mount
  (lesson change or "Reinitialiser").
- Terminal output keeps its spacing (git branch indentation, git status
  tabs); the welcome message, instruction, success message and hint no longer
  show raw markdown backticks and asterisks.
- The Windows hint of the scripts lesson now says to `cd projets` first.

Permanent guard: lessonFidelity.test.ts replays, for every lesson x
environment, the command the lesson tells the learner to type, and requires
it to validate AND print no error. The solutions table must match the
lesson's instruction or hint word for word, so it cannot drift. The 9 cases
still broken in the engine (2>, ./script.sh, $PROFILE, three PowerShell
cmdlets) run as it.fails in a ratchet that can only shrink: fixing one turns
the suite red until its entry is removed.

Replayed in the engine with the full lesson commands, 44 combinations
failed before this change; 35 are fixed here, 9 remain in the ratchet (the
census counted 46 because it also typed fragments of the hints). Bundle: +0.06 kB gzip (LessonPage), +0.7 kB (curriculum).

Refs THI-353

Co-Authored-By: Claude Opus 5.5 <[email protected]>

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @thierryvm, you've used your own review budget of 250,000 diff characters for the last 7 days.

You can request another review in 2 days and 20 hours by commenting @sourcery-ai review. Upgrade to get a review now.

@vercel

vercel Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
terminal-learning Ready Ready Preview Sep 23, 2026 10:11pm UTC

@sourcery-ai

sourcery-ai Bot commented Sep 23, 2026

Copy link
Copy Markdown

Guide du réviseur

Cette PR synchronise les instructions des leçons avec le contexte initial du terminal en ajoutant des constructeurs d’état purs par leçon, en les intégrant à l’initialisation unique du terminal, en améliorant le rendu du texte du terminal et en garantissant la fidélité des leçons entre les environnements grâce à des tests de régression et à un mécanisme de suivi des lacunes connues du moteur.

Diagramme de séquence pour l’initialisation du terminal spécifique à une leçon

sequenceDiagram
    participant LessonPage
    participant TerminalEmulator
    participant LessonSetup
    participant TerminalEngine

    LessonPage->>LessonPage: buildInitialState()
    LessonPage->>LessonSetup: apply(createInitialState())
    LessonSetup-->>LessonPage: prepared TerminalState
    LessonPage->>TerminalEmulator: initialState=buildInitialState
    TerminalEmulator->>TerminalEmulator: useState(initialState)
    TerminalEmulator->>TerminalEngine: execute command
    TerminalEngine-->>TerminalEmulator: output and validation result
Loading

Diagramme de flux pour la validation de la fidélité des leçons

flowchart LR
    Lessons[Every lesson] --> Environments[Every environment]
    Environments --> Instruction[Lesson instruction or hint]
    Instruction --> Replay[Replay command in prepared terminal]
    Replay --> Validate["validate(command, env)"]
    Replay --> Output[Terminal output]
    Validate --> Pass[Validation succeeds]
    Output --> Clean[No error line]
    Pass --> Fidelity[Lesson fidelity passes]
    Clean --> Fidelity
Loading

Modifications au niveau des fichiers

Modification Détails Fichiers
Introduit des constructeurs réutilisables et immuables pour la configuration du terminal des leçons nécessitant des contextes Git ou de système de fichiers préparés.
  • Ajoute des métadonnées de configuration avec des transformations d’état pures et des notes destinées aux apprenants.
  • Prépare les dépôts avec le répertoire, les commits, les branches, les dépôts distants et les permissions SSH requis.
  • Associe ces configurations aux exercices Git et de sécurité, et corrige les instructions relatives aux scripts Windows.
src/app/data/lessonSetup.ts
src/app/data/curriculum.ts
Permet au terminal d’utiliser l’état initial spécifique à chaque leçon tout en conservant un affichage lisible des commandes.
  • Construit l’état initial une seule fois par montage/réinitialisation du terminal grâce à un initialiseur différé.
  • Préserve les espaces et renvoie les jetons de sortie longs à la ligne sur les écrans étroits.
  • Conserve l’état par défaut pour les terminaux sans configuration.
src/app/components/LessonPage.tsx
src/app/components/TerminalEmulator.tsx
Supprime les marqueurs Markdown intégrés du texte destiné au terminal et affiche le Markdown dans l’interface de la leçon.
  • Ajoute un utilitaire de suppression du Markdown en texte brut pour les messages de bienvenue.
  • Affiche le texte des instructions, des indices et des réussites sous forme de Markdown en ligne lorsque cette fonctionnalité est prise en charge.
  • Teste la gestion complète et incomplète des marqueurs Markdown en ligne.
src/lib/renderInlineMarkdown.tsx
src/app/components/LessonPage.tsx
src/test/renderInlineMarkdown.test.tsx
Ajoute une couverture de régression qui compare les instructions des leçons au comportement réel du terminal dans différents environnements.
  • Rejoue la solution de chaque leçon sous Linux, macOS et Windows, en exigeant une validation sans sortie d’erreur.
  • Utilise des entrées d’échecs attendus comme mécanisme de suivi visant à réduire les désynchronisations restantes du moteur.
  • Vérifie la couverture de la table des solutions et la présence exacte des commandes dans le texte des leçons.
src/test/lessonFidelity.test.ts
src/test/lessonSolutions.ts
Ajoute des tests ciblés pour l’immuabilité des configurations, le comportement des commandes préparées et l’initialisation du terminal.
  • Vérifie le contenu et les permissions des configurations Git et SSH, l’espacement de la sortie et le comportement de l’état par défaut.
  • Confirme que les constructeurs de configuration ne sont appelés qu’une seule fois et que l’état fourni est transmis au traitement des commandes.
src/test/lessonSetup.test.ts
src/test/terminalEmulatorInitialState.test.tsx

Conseils et commandes

Interagir avec Sourcery

  • Déclencher une nouvelle révision : commentez @sourcery-ai review sur la pull request.
  • Poursuivre les discussions : répondez directement aux commentaires de révision de Sourcery.
  • Générer une issue GitHub à partir d’un commentaire de révision : demandez à Sourcery de créer une issue à partir d’un commentaire de révision en y répondant. Vous pouvez également répondre à un commentaire de révision avec @sourcery-ai issue pour créer une issue à partir de celui-ci.
  • Générer un titre de pull request : écrivez @sourcery-ai n’importe où dans le titre de la pull request pour générer un titre à tout moment. Vous pouvez également commenter @sourcery-ai title sur la pull request pour générer ou régénérer le titre à tout moment.
  • Générer un résumé de pull request : écrivez @sourcery-ai summary n’importe où dans le corps de la pull request pour générer un résumé de PR à tout moment, exactement à l’endroit souhaité. Vous pouvez également commenter @sourcery-ai summary sur la pull request pour générer ou régénérer le résumé à tout moment.
  • Générer le guide du réviseur : commentez @sourcery-ai guide sur la pull request pour générer ou régénérer le guide du réviseur à tout moment.
  • Résoudre tous les commentaires de Sourcery : commentez @sourcery-ai resolve sur la pull request pour résoudre tous les commentaires de Sourcery. Cette option est utile si vous avez déjà traité tous les commentaires et ne souhaitez plus les voir.
  • Ignorer toutes les révisions de Sourcery : commentez @sourcery-ai dismiss sur la pull request pour ignorer toutes les révisions existantes de Sourcery. Cette option est particulièrement utile si vous souhaitez repartir de zéro avec une nouvelle révision — n’oubliez pas de commenter @sourcery-ai review pour déclencher une nouvelle révision !

Personnaliser votre expérience

Accédez à votre tableau de bord pour :

  • Activer ou désactiver des fonctionnalités de révision telles que le résumé de pull request généré par Sourcery, le guide du réviseur, et d’autres fonctionnalités.
  • Modifier la langue de révision.
  • Ajouter, supprimer ou modifier des instructions de révision personnalisées.
  • Ajuster d’autres paramètres de révision.

Obtenir de l’aide

Original review guide in English

Reviewer's Guide

This PR synchronizes lesson instructions with the terminal’s starting context by adding pure per-lesson state builders, wiring them into one-time terminal initialization, improving terminal text rendering, and enforcing cross-environment lesson fidelity with regression tests and a ratchet for known engine gaps.

Sequence diagram for lesson-specific terminal initialization

sequenceDiagram
    participant LessonPage
    participant TerminalEmulator
    participant LessonSetup
    participant TerminalEngine

    LessonPage->>LessonPage: buildInitialState()
    LessonPage->>LessonSetup: apply(createInitialState())
    LessonSetup-->>LessonPage: prepared TerminalState
    LessonPage->>TerminalEmulator: initialState=buildInitialState
    TerminalEmulator->>TerminalEmulator: useState(initialState)
    TerminalEmulator->>TerminalEngine: execute command
    TerminalEngine-->>TerminalEmulator: output and validation result
Loading

Flow diagram for lesson fidelity validation

flowchart LR
    Lessons[Every lesson] --> Environments[Every environment]
    Environments --> Instruction[Lesson instruction or hint]
    Instruction --> Replay[Replay command in prepared terminal]
    Replay --> Validate["validate(command, env)"]
    Replay --> Output[Terminal output]
    Validate --> Pass[Validation succeeds]
    Output --> Clean[No error line]
    Pass --> Fidelity[Lesson fidelity passes]
    Clean --> Fidelity
Loading

File-Level Changes

Change Details Files
Introduces reusable, immutable terminal setup builders for lessons that require prepared Git or filesystem contexts.
  • Adds setup metadata with pure state transforms and learner-facing notes.
  • Prepares repositories with the required directory, commits, branches, remotes, and SSH permissions.
  • Attaches setups to Git and security exercises and corrects the Windows scripts guidance.
src/app/data/lessonSetup.ts
src/app/data/curriculum.ts
Makes the terminal consume lesson-specific initial state while preserving readable command output.
  • Builds initial state once per terminal mount/reset through a lazy initializer.
  • Preserves whitespace and wraps long output tokens on narrow screens.
  • Keeps terminals without setup on the default state.
src/app/components/LessonPage.tsx
src/app/components/TerminalEmulator.tsx
Removes inline Markdown markers from terminal-facing text and renders Markdown in the lesson UI.
  • Adds a plain-text Markdown stripping helper for welcome messages.
  • Renders instruction, hint, and success text as inline Markdown where supported.
  • Tests complete and unmatched inline Markdown token handling.
src/lib/renderInlineMarkdown.tsx
src/app/components/LessonPage.tsx
src/test/renderInlineMarkdown.test.tsx
Adds regression coverage that checks lesson instructions against actual terminal behavior across environments.
  • Replays every lesson solution for Linux, macOS, and Windows, requiring validation without error output.
  • Uses expected-failure entries as a shrinking ratchet for remaining engine desynchronizations.
  • Verifies solution-table coverage and exact command presence in lesson text.
src/test/lessonFidelity.test.ts
src/test/lessonSolutions.ts
Adds focused tests for setup immutability, prepared command behavior, and terminal initialization.
  • Verifies Git and SSH setup contents, permissions, output spacing, and default-state behavior.
  • Confirms setup builders are called only once and supplied state reaches command handling.
src/test/lessonSetup.test.ts
src/test/terminalEmulatorInitialState.test.tsx

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@thierryvm
thierryvm merged commit 24d77fe into main Sep 23, 2026
4 checks passed
@thierryvm
thierryvm deleted the feat/p1-lesson-setup-fidelity branch September 23, 2026 22:19

This branch was successfully deployed

1 active deployment
Preview — f70e85fc Deployed Sep 23, 2026 by vercel[bot]
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