Neuen Aufgabentyp hinzufügen¶
Das kanonische Modell wird nicht auf Vorrat erweitert. Ein neuer
Aufgabentyp kommt nur, wenn konkreter Content ihn braucht - und dann als eine
kleine, additive PR. Dies ist das verbindliche Rezept, abgeleitet aus der
realen cloze/select-Multiple-Choice-Arbeit (#1342) und der EXP-039-
Schema-Pipeline.
Bevor du beginnst: prüfe, ob es wirklich ein neuer Typ ist und nicht eine Darstellungsform oder eine Konvention, die der Aufgabentyp-Katalog schon abdeckt (Text-Multiple-Choice, Wahr/Falsch, Dropdown/Radio/Checkbox sind keine neuen Typen). Er muss binär SRS-bewertbar sein (ein einziges korrekt/falsch-Ergebnis pro Element) - das ist die Grenze, die die „Bewusst nicht"-Liste des Katalogs zieht.
Schritte¶
- EXP-Eintrag / Begründung. Bedarf, binäre Bewertungssemantik und
Abgrenzung zu bestehenden Typen in der passenden Exploration festhalten
(
docs/explorations/EXP-041-*für Aufgabentyp-Eignung, oder eine neue EXP). Kein Typ ohne dokumentierten Grund. - Das Format in der Engine erweitern. Das kanonische Zuhause des
Lektionsformats ist das Paket
learn-content-engine:
den Typ dort ins Schema, in die handgeschriebene semantische Schicht
(
validate.ts) und in die Format-Referenz aufnehmen, dann die Engine releasen. Eine Formatänderung beginnt in der Engine - dasschema/*.jsonder App ist ein Byte-Spiegel des gepinnten Release mit genau einem Schreiber (scripts/sync_schema_mirror_from_engine.py, #2265). - Pin bumpen, Sync laufen lassen. Den
learn-content-engine-Pin infrontend/package.jsonerhöhen, dannmake sync-schemaim selben PR: es frischt den Spiegelschema/*.jsonaus dem installierten Paket auf und regeneriert jedes abgeleitete Artefakt - die strukturelle Pydantic-Schicht (plugins/adaptive-learner-plugin-content-loader/adaptive_learner_content_loader/schema_generated.pyviascripts/generate_pydantic_models.py), die TS-Lektionstypen (frontend/src/storage/types/content/lesson-schema.generated.ts) und die Format-Referenz-Doku. Ein gespiegeltes oder generiertes Artefakt nie von Hand editieren; das Drift-Gatemake sync-schema-checkschlägt sonst fehl. - Semantische Schicht + Schema-Version. Die App-seitigen Feld-
übergreifenden Regeln als dünne Subklasse in
plugins/adaptive-learner-plugin-content-loader/adaptive_learner_content_loader/schema.pyergänzen (die strukturellen Felder sind generiert; nur die Semantik ist handgeschrieben) undCURRENT_SCHEMA_VERSIONinmodels.pyan der Schema-Version des gepinnten Engine-Release halten (Minor = additiv; alter Content bleibt über den Major-Version-Match gültig). - Renderer registrieren. Den Branch + den Typ zu
SUPPORTED_EXERCISE_TYPESinfrontend/src/components/exercises/shell/ExerciseDispatcher.tsxergänzen. Die Registry muss dem Enum entsprechen - ein Paritätstest erzwingt das, sodass ein nicht gerenderter Typ die CI bricht (die Invariante, die totes Schema verhindert). - Bewertung / SRS anschließen. Aus dem Renderer via
useControlledExerciseeinExerciseScoredausgeben; der geteilteonComplete-→-recordStepResult-Pfad inLessonStepView.tsxfächert jeden Versuch bereits übergetStorage().elementErrors.recordBulkauf - diesen wiederverwenden, keinen zweiten Aufzeichnungspfad bauen. - Content-Repo-Validierung. Den Client-Validator
(
frontend/src/lib/content/validation/content-validator.ts) erweitern. Die Qualitätsminima leben in derquality-rules.jsonder Engine (gespiegelt nachschema/quality-rules.json); berührt der Typ sie, werden sie in der Engine erweitert, nicht in der App. - Authoring-Doku. Den Typ in die
Katalog-Tabelle und einen
### <typ>-Referenzblock mit JSON-Beispiel aufnehmen (EN + DE). - Tests. Schema akzeptiert ein gültiges Beispiel und lehnt ein ungültiges ab (fehlendes Pflichtfeld / Extra-Key); der Renderer rendert + bewertet korrekt/falsch; der SRS-Versuch wird aufgezeichnet; mobile Visual-Baseline ergänzen, falls die Optik des Controls neu ist.
- Folge-Arbeit (nicht diese PR). Die Content-Repos
(
adaptive-learner-content) übernehmen den neuen Typ, wenn sie ihr Engine-Release neu pinnen; vermerken, nicht darauf warten.
Warum das klein bleibt¶
Weil das Format aus dem gepinnten Engine-Release gespiegelt wird und jedes App-Artefakt aus diesem Spiegel abgeleitet ist (Schritt 3) und der Dispatcher-Paritätstest Registry-gleich-Enum erzwingt (Schritt 5), ist ein neuer Typ eine additive Änderung mit fester Form: Engine → Pin → generieren → Renderer → Bewertung → Doku → Tests. Keine parallel handgepflegte Kopie kann driften, und kein Typ kann ohne Renderer ausgeliefert werden.