# Änderungsverlauf Alle nennenswerten Änderungen an dieser Anwendung stehen hier, neueste zuerst. Das Format folgt [Keep a Changelog](https://keepachangelog.com/de/1.1.0/), die Nummerierung [Semantic Versioning](https://semver.org/lang/de/): - **Hauptnummer** (1.0.0) — erst mit dem Abschluss der Barrierefreiheitsprüfung. Solange die Null vorn steht, ist der Funktionsumfang noch nicht vollständig. - **Nebennummer** (0.**9**.0) — neue Merkmale. - **Fehlernummer** (0.9.**1**) — nur Fehlerbehebungen. Dieses Dokument sagt, *was sich geändert hat* — nicht, welche Merkmale es gibt und welche fehlen. Jede veröffentlichte Fassung trägt ein Git-Etikett (`v0.9.0`) und ein Installationspaket unter `app/release/`. In der Anwendung selbst stehen Programmversion und Baustand unter „Systemzustand“ auf dem Startbildschirm; ein `+` hinter der Baukennung heißt, dass beim Bauen unversionierte Änderungen im Arbeitsbaum lagen. --- ## [Unveröffentlicht] Seit der Fassung 0.26.7 hat sich nichts geändert. ## [0.26.7] — 2026-09-01 Der letzte offene Befund der Stand-der-Technik-Runde, der sich bauen ließ. ### Für die Öffentlichkeit - **Ein Knopf führt jetzt zu den selbsttätigen Sicherheitskopien.** Bisher erzählte die Karte von ihnen, ohne dass ein Weg hinführte — wer eine Kopie im Ernstfall brauchte, musste den Pfad kennen. „Ordner der Sicherheitskopien öffnen“ steht unter „Lernstand sichern und übertragen“. ### Behoben - **Der Weg zu den Sicherheitskopien fehlte vollständig.** Kein Kanal listete den Ordner, kein Dateidialog zeigte hin, und der Ordnername kam in der ganzen Oberfläche nicht vor. Gibt es den Ordner noch nicht — er entsteht mit der ersten Kopie —, sagt die Karte das, statt so zu tun, als sei etwas geschehen. ### Für die Werkbank - **Der neue Kanal `sicherung:ordner-zeigen` nimmt kein Argument.** Welcher Ordner gemeint ist, entscheidet der Hauptprozess. Ein Kanal, der einen Pfad entgegennähme, wäre ein Weg, beliebige Ordner des Rechners zu öffnen — und der Renderer hat in diesem Projekt keinen Node-Zugriff, gerade damit es solche Wege nicht gibt. - **`ordnerZeigen` ist das Gegenstück zu `dateiZeigen`.** Jenes nimmt ausschließlich eine Kennung entgegen, weil aus dem Renderer nie ein Pfad kommen darf; dieses nimmt einen Pfad, weil er aus dem Hauptprozess selbst stammt. Der Unterschied steht an beiden Funktionen. - **Der volle Weg nach Hausregel:** Eintrag in `IpcVertrag` und `IPC_KANAELE`, Handler über `behandeln()`, Methode in `LernAppBridge` und im Preload-Skript. - **Drei Wachen, gegengeprobt:** der geöffnete Ordner, der noch nicht vorhandene, und der fehlende Kanal. Ohne den Knopf sind alle drei rot. - Zahlen: **1778 Vitest-Tests in 77 Dateien** (vorher 1775). ## [0.26.6] — 2026-09-01 Die Befundliste der Stand-der-Technik-Runde wird abgearbeitet. Dreizehn Befunde sind am Quelltext gegengeprüft worden, mit dem ausdrücklichen Auftrag, sie zu **widerlegen** — **vier davon fielen dabei**. Gebaut ist, was standgehalten hat. ### Für die Öffentlichkeit - **Wie viele Fragen eine Lernsitzung umfasst, lässt sich jetzt einstellen** — fünf bis fünfzig statt der festen zwanzig. Eine beendete kurze Sitzung ist mehr wert als eine liegengelassene lange. - **Haben Sie viel nachzuholen, kommt zuerst, was Sie am ehesten vergessen haben.** Bisher entschied der Zufall, welche der fälligen Fragen in eine Sitzung kamen. - **Gleich bewertete Fragen desselben Tages bekommen nicht mehr denselben Termin.** Die Wiederholungen verteilen sich, statt sich zu Bergen zu türmen. - **Fragen aus einem Bereich mit besonderer Fehlergrenze kommen häufiger.** In Notwehr und Notstand lassen manche Prüfungsstellen nur wenige Fehler zu; die Wiederholung berücksichtigt das jetzt so wie die Reifeanzeige. - **Die Restzeit lässt sich in der Simulation ansagen** — auf die Sekunde genau, ohne dass die Anzeige unruhig wird. - **Auch im Prüfungsbogen lässt sich eine Frage merken.** Für den Fall, den die Auswertung nicht kennt: geraten und richtig getroffen. - **Vor „Neu anfangen“ und vor dem Löschen eines Profils entsteht eine Sicherheitskopie**, und die Sicherungskarte sagt jetzt, wo die selbsttätigen Kopien liegen. ### Behoben - **Der Gesetzesabzug sagt jetzt, wann er gezogen wurde.** `content/gesetze/index.json` führte die amtliche Standangabe jedes Gesetzes, aber nirgends stand, wann jemand zuletzt nachgesehen hat, ob es dabei geblieben ist. Zwischen dem ältesten Abzug (Beschussgesetz, 09.09.2020) und dem jüngsten (Sprengstoffgesetz, 23.07.2026) liegen fast **sechs Jahre**; alle 1854 Fundstellen werden gegen genau diesen Bestand geprüft. `docs/veroeffentlichen.md` hat dafür jetzt einen Schritt, vier Wachen halten ihn fest. - **Der Planer kennt jetzt die K.-o.-Bereiche.** Die Reifeampel deckelt ihr Gesamturteil seit 0.22.0 am schwächsten Bereich mit K.-o.-Kriterium — wer insgesamt gut dasteht und in Notwehr zurückliegt, bekommt kein „Prüfungsreif“. Die Wiedervorlage wusste davon nichts und terminierte die **43** Fragen aus I.5 wie jede andere. Sie hält dort jetzt eine Zielquote von mindestens 0,95. - **Bei Rückstand entscheidet nicht mehr das Los.** Standen 100 Fragen fällig und die Sitzung fasste 20, wurde die fällige Gruppe gemischt und abgeschnitten. Vorgelegt wird jetzt zuerst, was am wahrscheinlichsten schon vergessen ist. ### Für die Werkbank - **Vier Befunde sind widerlegt worden**, jeder mit Belegstelle: die behauptete Uneinigkeit zwischen Fälligkeit (24-Stunden-Blöcke) und Vorschau (Kalendertage) ist die **Behebung** von Befund H5 und kein Versehen; `setAccessibilitySupportEnabled` fehlt, aber die Anwendung **liest** den Zustand über `system:hilfsmittel` und richtet die Zeichenkürzel danach aus; das Anhalten der Simulation ist über das Schließen des Fensters samt Rückfrage, stehender Uhr und Wiederaufnahme gebaut; und eine bestätigte Auswahlantwort lässt sich sehr wohl zurücknehmen, solange die Buchung aussteht. - **Warum 0,95 und nicht 0,97 für die K.-o.-Bereiche.** Nachgerechnet mit den Parametern dieses Projekts: Bei einer Stabilität von 60 Tagen ergibt 0,90 ein Intervall von **62** Tagen, 0,95 eines von **25**, 0,97 eines von 13. Die Terminquote dauerhaft anzulegen hieße, diese Fragen viereinhalbmal so oft vorzulegen — auch ein Jahr vor der Prüfung. Sobald der Termin naht, steigt die allgemeine Quote ohnehin darüber. - **Sortiert wird nach Abrufwahrscheinlichkeit, nicht nach Überfälligkeit.** Eine Frage mit kleiner Stabilität ist nach einem Tag schon weg, eine gefestigte nach dreißig noch da; die Überfälligkeit allein misst das Falsche. `abrufwahrscheinlichkeit` war bereits gebaut. - **Eine Wache bestand ihre Gegenprobe zunächst nicht.** Der erste Entwurf war auch ohne die Behebung grün: Fisher-Yates mit einer Zufallsquelle, die stets 0 liefert, **kehrt ein Zweierfeld um** — und sortierte die schwache Frage zufällig richtig ein. Mit 0,99 bleibt die Katalogfolge stehen, und die alte Fassung fällt nachweislich durch. Ohne die Gegenprobe wäre eine wertlose Zusicherung eingezogen. - **Bewusst keine Altersprüfung des Gesetzesabzugs.** Ein Test, der allein durch Zeitablauf rot wird, meldet an seinem Tag keinen Befund, sondern eine Störung — dieselbe Bauart, die in `selbstsicherung.test.ts` heute früh zugeschlagen hat. Geprüft wird, dass die Angabe **da** ist; hinsehen muss die Veröffentlichungsliste. - **Die Streuung stammt aus der Frage-Kennung, nicht aus einer Zufallsquelle.** Der erste Entwurf nahm `this.zufall` des Lernstands und fiel sofort auf: Zwei fremde Zusicherungen wurden dadurch **zufällig**, eine davon ohne jede Berührung. Ein Verfahren, das reproduzierbare Zahlen liefert, darf nicht an einer Quelle hängen, die es nicht kennt. - **Die Streuung wirkt in die Rechnung zurück** — wie bei Anki: Der tatsächliche Abstand ist der gestreute, und er geht in den nächsten Gedächtnisstand ein. Vier Zusicherungen in `lernstand.test.ts` messen deshalb andere Zahlen als vorher; sie messen den **Termin**. Das reine Verfahren bleibt gepinnt, wo es hingehört: `fsrs.test.ts` gegen py-fsrs und `lernplan.test.ts` an `wiedervorlageBerechnen`, beide unverändert grün. - **Höchstens 15 Prozent, gedeckelt auf sieben Tage, erst ab drei Tagen.** Darunter wäre ein Tag Versatz keine Streuung mehr, sondern eine andere Antwort: Bei Intervall 1 hieße „ein Tag früher“ noch heute. - **Die Kopie vor dem Verwerfen unterscheidet sich in drei Punkten von der Wochenkopie:** Sie ist **ungedrosselt** (die Wochenkopie schweigt, wenn die letzte noch frisch ist – genau das wäre hier der Ausfall), sie führt einen **eigenen Vorsatz und ein eigenes Kontingent** (sonst räumten die Wege sich gegenseitig ab), und sie **wirft**. Beim Beenden ist die Kopie eine Zugabe; vor einem Schritt, der Daten vernichtet, ist sie die Bedingung. - **Auch die Verdrahtung ist bewacht.** Für die IPC-Schicht gibt es in diesem Projekt keinen Prüfstand; drei Zusicherungen lesen deshalb den Quelltext – wie `sicherheit.test.ts` es mit dem Sicherheitsmodell tut – und prüfen, dass der Aufruf **vor** dem zerstörenden Schritt steht und dass sein Fehlschlag **nicht** abgefangen wird. Gegengeprobt: Ohne den Aufruf wird die Zusicherung rot. - **Der Merkknopf im Bogen holt seinen Zustand nach.** Anders als `SitzungsFrage` bringt `Pruefungsfrage` ihn nicht mit: Der Bogen entsteht im Renderer aus dem Katalog (`bogenAusKatalog`) und kennt den Lernstand nicht. Geholt wird er über `lernen:fragestand`, sobald die Frage erscheint — einmal je Frage, gemerkt in einem `useRef` und nicht im Zustand, weil das Bild sich davon nicht ändert und `setState` im Effekt die Projektregel verletzte. - **Die Ansage hängt an ihrer Frage**, nicht an einem Zeitgeber: `ansage` wird in diesem Haken abgeleitet und nicht gesetzt, und ein „Frage gemerkt“, das beim Blättern stehen bliebe, wäre eine Falschaussage. - **Misslingt das Speichern, verschwindet das Merkzeichen wieder.** Eines, das nach dem Lauf fehlt, wäre schlimmer als eines, das gar nicht erst erscheint. - **Die Restzeit wird auf die Sekunde genau angesagt, die Anzeige bleibt bei Minuten.** Zwei Fragen innerhalb derselben Minute müssen zwei verschiedene Sätze ergeben – in einer Live-Region, in der zweimal dasselbe steht, meldet sich beim zweiten Mal nichts, und der Knopf wirkte kaputt. Dafür gibt es `restzeitGenau` neben `restzeitText`. - **Die zweite Live-Region erscheint erst, wenn etwas darin steht.** Sonst fanden zwei bestehende Zusicherungen zwei Knoten mit `role="status"` – ein Fund der Wachen, kein Zufall. - **Der Sitzungsumfang wird im Hauptprozess geprüft, nicht in der Oberfläche.** `main/einstellungen.ts` nimmt 1 bis 1000 an, dieselbe Spanne wie `Lernstand.sitzung`; ein von Hand verstellter Wert in der Datei schlägt damit nicht durch, und eine Einstellung, die der Kern danach zurückwiese, wäre eine Falle. - **Nicht gebaut: ein Knopf, der den Sicherungsordner öffnet.** Der Kanal `system:datei-zeigen` könnte es, verlangt aber eine Kennung aus `main/dateizugriff.ts` – und der Weg, sie in die Oberfläche zu bekommen, wäre ein neuer IPC-Kanal. Die Gegenprüfung hatte hier ausdrücklich den kleinen Eingriff empfohlen; er ist gemacht, der große bleibt offen. - Zahlen: **1775 Vitest-Tests in 77 Dateien** (vorher 1746). ### Offen aus derselben Liste Ein bestätigter Befund ist noch nicht gebaut: Vor „Neu anfangen“ und vor dem Löschen eines Profils entsteht keine Sicherheitskopie, obwohl beide Einspielwege selbstverständlich eine anlegen. Dazu fünf Befunde, die die Gegenprüfung als **teilweise** zutreffend einstuft. ## [0.26.5] — 2026-09-01 Der angekündigte Durchgang über die Antwortkommentare — mit einem anderen Ergebnis als erwartet. Der Befund, der ihn ausgelöst hat, war ein Messfehler. ### Für die Öffentlichkeit - **Zwei Erklärungen sagen jetzt auch, warum die übrige Antwortmöglichkeit nicht stimmt.** Bei der Geltungsdauer eines Voreintrags und beim Mindestalter für Sportschützen stand bisher nur, was gilt — nicht, woran die naheliegende Verwechslung scheitert. ### Behoben - **Der Befund „224 von 471 Erklärungen benennen keine einzige Antwortmöglichkeit“ war falsch.** Er zählte allein die Schreibweise „a)“. Der Hausstil kennt aber mehrere: „Antwort b“, „Zu c“, „Buchstabe d“ — und vor allem den Weg über den Gegenstand statt über den Buchstaben („die Armbrust scheitert am Lauf“). - **Zwei Erklärungen ergänzt**, bei denen eine Möglichkeit tatsächlich unbehandelt blieb: I.1-74 („6 Monate“ — das Gesetz nennt diese Frist an keiner Stelle, § 10 Abs. 1 Satz 3 kennt nur das Jahr) und I.2-23 („durch ein fachärztliches Gutachten“ — das gehört nach § 6 Abs. 2 zur persönlichen Eignung, und das Mindestalter des § 14 Abs. 1 ist keine Eignungsfrage). ### Für die Werkbank - **Die Messkette, Schritt für Schritt:** 224 → 220 (eigene Nachzählung der Buchstabenform) → 111 (Optionen, die auch dem Gegenstand nach fehlen) → 33 (mit Buchstabenformen des Hausstils) → 8 (mit Wortstamm statt Wortgleichheit) → **0** (von Hand nachgesehen: alle acht waren angesprochen, unter anderem mit „Keine.“, „Nein.“, „Zulässig“ und „über Bord geworfen“). Übrig blieben nach der geschärften Prüfung genau **zwei** echte Fälle. - **Jede Zwischenstufe war ein Fehler in meiner Messung, nicht im Bestand.** „WBK“ gegen „Waffenbesitzkarte“, „Leuchtpunktvisiere“ gegen „Leuchtpunktvisier“, „Armbrust“ gegen „Armbrüste“, „Monats“ gegen „Monat“, „werfen“ gegen „geworfen“. Wer eine Textmenge mit Wortgleichheit misst, misst die eigene Wortliste. - **Neue Prüfung `optionen_pruefen` in `pruefe_erklaerungen.py`.** Sie verlangt, dass jede Antwortmöglichkeit vorkommt — mit ihrem Buchstaben **oder** mit ihrem Gegenstand. Umlaute werden gefaltet, Wortstämme statt Wortgleichheit verglichen, und eine Möglichkeit, die aus nichts als „Nein“ besteht, gilt als behandelt, sobald die Kurzfassung ein Urteil spricht: Sie ist die Verneinung der ganzen Frage, und ein Satz „Antwort c ist falsch“ brächte dort nichts, was nicht schon dastünde. - **Gegengeprobt in beide Richtungen:** Mit den zwei Ergänzungen meldet die Prüfung nichts; wird eine davon wieder herausgenommen, meldet sie genau diese Möglichkeit. 1854 Fundstellen, alle nachgewiesen. - **Warum der Weg über den Gegenstand der bessere ist.** Wer sich die Erklärung vorlesen lässt, hört bei „zu a)“ nichts, woran er sich erinnern könnte — der Buchstabe steht auf dem Bildschirm, nicht im Ohr. 341 der 471 Erklärungen gehen deshalb über die Sache. Eine Umstellung auf Buchstaben wäre eine Verschlechterung gewesen. - **`docs/stand.md` trug die falsche Zahl seit 0.26.4** und ist berichtigt. - Zahlen: **1742 Vitest-Tests in 77 Dateien**, 1854 Fundstellen (vorher 1853), ESLint ohne Warnung. ## [0.26.4] — 2026-09-01 Die ersten Befunde aus der Prüfung, ob diese Software dem Stand der Technik entspricht. Acht Felder wurden gegen die heutige Fachliteratur und den Wettbewerb gehalten; hier stehen der eine echte Defekt und die drei Lücken mit dem besten Verhältnis von Nutzen zu Aufwand. ### Für die Öffentlichkeit - **Ein abgewähltes Kapitel bleibt auch auf dem zweiten Rechner abgewählt.** Wer seinen Lernstand auf ein anderes Gerät überträgt, bekam dort bisher stillschweigend alle Kapitel zurück — auch die, die er für seine Prüfung gar nicht braucht. Die Prüfungsreife-Anzeige fiel dadurch um zwei Stufen, ohne dass etwas darauf hinwies. - **Der Vergleich zweier Simulationen sagt jetzt, wann ein Unterschied nichts bedeutet.** Ein Bogen zieht seine Fragen aus dem gesamten Bestand; zwei Läufe fallen deshalb schon durch die Ziehung auseinander, auch wenn sich am Wissen nichts geändert hat. Liegt der Unterschied darunter, steht das jetzt dabei — mit der Zahl der Fragen, um die es tatsächlich geht. - **Das Handbuch erklärt, wie man eine frei zu formulierende Antwort aufbaut.** 104 der 575 Fragen verlangen eine eigene Antwort, und sie werden von Menschen bewertet. Woran man erkennt, was verlangt ist, steht jetzt im Kapitel zur Lernsitzung. - **Und es sagt, dass ein Nachteilsausgleich beantragt werden muss.** Die Anwendung bietet die verlängerte Zeit zum Üben an. In der Prüfung ist sie kein Selbstläufer: Wer sie braucht, muss sie bei der Stelle beantragen, die seine Prüfung abnimmt. Das Kapitel zur Simulation sagt jetzt, wen man fragt und wonach. ### Behoben - **Die Kapitelabwahl reiste beim Übernehmen eines Profils nicht mit.** `profil-uebernehmen.ts` las aus der Quelle nur `name` und `pruefungstermin`; `kapitel_ausschluss` steht als Spalte am Profil und nicht in einer Kindtabelle, wurde von der Schleife über `KINDTABELLEN` also nicht erfasst und fiel auf den Vorgabewert `'[]'` zurück. Die Folge ist in `shared/verlust.ts` seit jeher ausgerechnet: derselbe Bestand von **85,0 auf 71,9 Prozent**, zwei Ampelstufen. Kein Test sah hin. - **Der Laufvergleich meldete Rauschen als Fortschritt.** „5 Prozentpunkte besser“ sind bei einem Bogen von 80 Fragen vier Fragen — weniger, als zwei Ziehungen aus demselben Bestand ohnehin auseinanderliegen. ### Für die Werkbank - **Der Defekt saß im Weg, den das Handbuch selbst empfiehlt.** Zwei Geräte über die Sicherungsdatei zu verbinden ist die dokumentierte Lösung; genau dort ging die Abwahl verloren. Die neue Wache setzt in der Quelle `kapitel_ausschluss = '["IV"]'` und prüft es am Ziel nach. - **Die Abfrage greift nur, wenn die Quelle die Spalte kennt.** Eine Sicherung von vor 0.20.0 hat sie nicht; dort ist „nichts abgewählt“ die richtige Annahme. Der vorhandene Test über ältere Quellen bleibt grün. - **Warum die binomiale Streuung hier trägt, obwohl der Reifegrad sie ausschlägt.** `entscheidung-reifegrad.md` Abschnitt 5 lehnt eine Bestehenswahrscheinlichkeit ab, weil die Trefferchancen je Frage zweigipflig verteilt sind. Das trifft eine **Prognose**. Beim bereits gezogenen Bogen hebt sich die Zweigipfligkeit auf: Eine zufällig gezogene Frage zu beantworten ist selbst ein Bernoulli-Versuch mit der mittleren Trefferchance. Mit **200 000 Läufen** gegen die in der Notiz beschriebene Verteilung nachgerechnet — bei 85, 70 und 50 Prozent gefestigter Fragen lag die gemessene Streuung jedes Mal **unter** der binomialen (11,63 zu 12,51 · 15,36 zu 16,87 · 16,97 zu 18,73). Die Endlichkeitskorrektur bliebe zusätzlich draußen. Die Schätzung ist also die vorsichtige Seite. - **Ein bestehender Test musste seine Erwartung ändern, und das ist der Befund.** `verlaufsvergleich.test.ts` prüfte mit `toEqual([])`, dass es keine Vorbehalte gibt — an Werten, die selbst ein Rauschfall sind: 80 Fragen, 75 gegen 80 Prozent. Die Zusicherung war zu weit gefasst; sie prüft jetzt, was ihr Name verspricht. - **Die Zahlen im Handbuch sind an den Katalog gebunden.** `tests/hilfe-zahlen.test.ts` zählt die 104 offenen Fragen und ihre Anfangswörter (26 „Was“, 25 „Welche“, 7 „Wie“, je 5 „Wann“ und „Nennen Sie“) bei jedem Lauf nach und liest die Zahlen aus dem Handbuchtext selbst, nicht aus einer zweiten Liste daneben. Gegengeprobt: eine verstellte Ziffer macht ihn rot. - **Der Entwurf zum Handbuch war zuerst falsch.** Er nannte „Erläutern Sie …“ als Beispiel einer Fragestellung — nachgezählt kommt das Wort im ganzen Katalog nicht vor. Und die Regel „zählen Sie, wie viele Punkte gefragt sind“ galt nur für **5 von 104** Fragen. Beides steht jetzt so da, wie es gemessen ist. - **Nachteilsausgleich: nachgeschlagen statt behauptet.** `data-pipeline/gesetz.py --suche` findet das Wort in keinem der beigelegten Gesetze. Genannt sind deshalb nur belegte Stellen: § 2 Absatz 1 AWaffV (die zuständige Behörde bildet die Prüfungsausschüsse), § 3 Absatz 5 (schießsportliche Vereine dürfen für ihre Mitglieder prüfen), § 2 Absatz 3 (theoretischer **und** praktischer Teil) und § 2 Absatz 5 (Wiederholung, Frist möglich). - Zahlen: **1742 Vitest-Tests in 77 Dateien** (vorher 1734), ESLint ohne Warnung. --- Fruehere Fassungen sind in dieser Ausgabe nicht einzeln aufgefuehrt. Die Entwicklung bis zum 31.08.2026 ist im Ausgangs-Commit dieses Archivs zusammengefasst.