Schließt die MCP-Server-Spec ab. "Worksheets" aus der Spec entsprechen
im tatsächlichen Datenmodell den .lavorlage-Elternbrief-Vorlagen
(LehrerApp.Templating) - es gibt kein separates Arbeitsblatt-Konzept mit
Fach/Klassenstufe-Metadaten. Neue Tools list_letter_templates (Read) und
render_letter (Read, liefert Base64-PDF, kein DB-Schreibzugriff).
upload_worksheet/update_worksheet bewusst nicht umgesetzt: das
Seitenlayout ist eine eigene positionsbasierte DSL mit eigenem
visuellen Editor (LehrerApp.TemplateDesigner) - ein LLM müsste sie
blind erzeugen, mit hohem Risiko für kaputte Layouts. Platzhalter-Logik
aus CreateLetterDialogViewModel nach LetterPlaceholderBuilder extrahiert,
damit Dialog und MCP-Tool nicht auseinanderdriften.
Neuer McpClientRegistrationService trägt den Bridge-Pfad in Claude
Desktops claude_desktop_config.json ein (Button in den Einstellungen,
nie automatisch), ohne bestehende Fremdeinträge zu verlieren und ohne
eine nicht lesbare Konfigurationsdatei zu überschreiben.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Erlaubt einem lokalen KI-Client (z.B. Claude Desktop) strukturierten
Lesezugriff auf Schüler, Klausuren, Noten, Stundenplan und Zeiterfassung.
Neuer LehrerApp.McpBridge-Prozess reicht stdio-JSON-RPC über eine Named
Pipe an einen In-Process-MCP-Server im Avalonia-Hauptprozess durch
(ModelContextProtocol.Core, StreamServerTransport direkt auf der Pipe).
Standardmäßig deaktiviert, Opt-in über neuen Einstellungen-Tab.
Dokumentationstypen (Gesprächsnotizen/Vorfälle/Förderpläne) sind auf
Code-Ebene nie erreichbar (McpToolScope, analog PlainEventStore.Allowed).
Write-Tools, Bestätigungsdialog-UI, Worksheets/Lesson-Plans-Tools und
macOS-Packaging folgen in späteren Phasen (siehe TODO.md 4.5.25).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Dashboard: Fehlzeiten-Warnung lädt Mitarbeitssitzungen einmal vorab
statt pro Schüler/Eintrag einzeln nachzuschlagen (N+1 vermieden);
neues IParticipationSessionRepository.GetAll() dafür.
- CI: .gitea/workflows/ci.yml baut und testet bei jedem Push/PR.
Dabei fehlende Release|Any CPU-Konfiguration für 6 Projekte in der
.sln behoben (LehrerApp.Data.Tests wurde bei Release-Builds der
Solution bislang stillschweigend übersprungen). TreatWarningsAsErrors
jetzt aktiv.
- SettingsViewModel (1986 Zeilen) als partial class auf 20 Themen-
dateien aufgeteilt, Verhalten unverändert.
- Backup: optionaler zweiter Sicherungsordner (USB-Stick/Netzlaufwerk,
best-effort) und Integritätsprüfung nach jedem Backup
(DatabaseEncryptionService.CanOpenAndRead).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Nutzer-Feedback: Klassenlehrer ist eine Rolle für die ganze Klasse, unabhängig vom
eigenen Unterricht - die Anbindung an ein LearningGroup.IsClassTeacher-Flag mit Tab
in der Gruppendetailansicht war deshalb der falsche Ort. Ersetzt durch:
- Klassenauswahl in den WebUntis-Einstellungen (WebUntisSettingsService.HomeroomClassName),
über den bestehenden WebUntis-Klassenpicker.
- Eigener Sidebar-Bereich "Klassenlehrer" statt Gruppen-Tab.
- Zwei Ebenen: kompakte Roster-Übersicht mit Ampel-Symbolen (Fehlzeiten heute,
Klassenbuch-Badge) und Details (die bisherigen Rohdaten-Listen, jetzt gefiltert
auf einzelne Schüler*innen anspringbar).
Noch nicht mit echtem WebUntis-Zugang gegengeprüft (siehe TODO.md).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Erkennt Vertretungen, Ausfälle und Zusatzaufsichten aus dem persönlichen
WebUntis-iCal-Feed und schreibt sie automatisch als SubstitutionEntry.
Bekannter offener Bug: es tauchen weiterhin falsche Vertretungen für
Stunden auf, die real unverändert sind — wird in einem Folge-Commit
untersucht, deshalb vorerst auf diesem Branch statt main.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Dunkelmodus über neuen Einstellungen-Tab "Darstellung" (Systemvorgabe/Hell/Dunkel),
Fenstergröße/Maximiert-Status wird über Sitzungen hinweg gemerkt (bewusst ohne
Fensterposition), und ein generischer Snapshot-basierter Papierkorb (30 Tage) für
Sitzpläne, Noten, Notenschlüssel-Vorlagen, Aufgaben und Zeiteinträge. Details und
bewusste Scope-Entscheidungen (Spaltenbreiten zurückgestellt, Farb-Audit für
Dunkelmodus offen, welche Entitäten der Papierkorb abdeckt) in TODO.md.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Der Sync-Schlüssel verlässt nie den Server im Klartext - verliert das einzige Gerät sync.key,
erzeugte AppBootstrapper bisher stillschweigend einen neuen, unabhängigen Schlüssel, ohne dass
der Nutzer etwas davon merkt. Bereits synchronisierte Server-Daten werden dadurch dauerhaft
unlesbar.
AppBootstrapper erkennt jetzt, ob ein fehlender Schlüssel bei einem bereits eingeloggten Gerät
auftritt (SyncKeyStatus) - SettingsViewModel zeigt dafür ein Warnbanner im Synchronisation-Tab mit
der Empfehlung, im Zweifel über ein noch intaktes zweites Gerät neu zu koppeln.
Zusätzlich ein komplett offline laufender, selbstverwalteter Wiederherstellungscode (kein neuer
dauerhafter Server-Speicher für ein sicherheitsrelevantes Geheimnis): SyncCrypto bekommt einen
neuen, vom Pairing-Code kryptografisch unabhängigen Recovery-Code (120 Bit, Base32), mit dem der
Sync-Schlüssel lokal verschlüsselt und als Datei durch den Nutzer selbst gesichert werden kann.
Neuer SyncKeyRecoveryService kapselt Erzeugen/Einlösen; Redeem schreibt den wiederhergestellten
Schlüssel und setzt vorsorglich Pull-Cursor/Versionsverfolgung zurück.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Nach einem Login mit korrigierter Groß-/Kleinschreibung (siehe vorheriger Fix zur userId-
Stabilität) bezog sich die lokale Versionsverfolgung je Entität (BasedOnServerSeq-Cache) und der
Pull-Cursor weiterhin auf das alte Konto - ServerSeq-Werte sind aber nur innerhalb des Event-Logs
EINES Kontos gültig. Der Push wurde zu Recht abgelehnt, der Server kannte die Entität unter der
neuen userId aber gar nicht (404 beim Nachladen), und HandleRejectedAsync gab bei einem 404
bisher einfach auf, ohne den veralteten Cache-Eintrag zu bereinigen - derselbe Fehlschlag bei
jedem weiteren Sync-Versuch.
Dreiteiliger Fix: (1) ein 404 beim Nachladen löscht jetzt den stale Cache-Eintrag, sodass der
nächste Push die Entität korrekt als neu behandelt und selbstheilend durchgeht; (2) der
"Vollständigen Sync erzwingen"-Button setzt jetzt auch die Push-Versionsverfolgung zurück, nicht
nur den Pull-Cursor; (3) SyncLogin erkennt einen echten Kontowechsel künftig proaktiv anhand der
kanonischen userId aus der Server-Antwort und resettet automatisch, bevor der Folgefehler
überhaupt auftreten kann.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
SyncEngine.PushAsync setzte den lokalen Pull-Cursor bisher aus PushResponse.ServerSequenceNr -
dem globalen Zähler über alle Geräte nach dem eigenen Push, nicht dem tatsächlich zugestellten
Stand. War beim Server zu diesem Zeitpunkt bereits ein noch nicht abgeholtes Ereignis eines
anderen Geräts mit niedrigerer ServerSeq vorhanden, sprang der Cursor darüber hinweg und der
direkt folgende Pull bekam 0 Ereignisse, ohne es je angewendet zu haben - ein zweiter,
unabhängiger Cursor-Bug mit demselben Symptom wie der vorherige Wasserzeichen-Fix, diesmal
client- statt serverseitig.
Ergänzt außerdem einen "Vollständigen Sync erzwingen"-Button in den Sync-Einstellungen, damit
bereits durch diesen Bug zu weit vorgerückte Geräte ihren Fortschritt manuell zurücksetzen und
alle Ereignisse erneut laden können.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
RedeemPairingCode() rief nach einem Fehlschlag sofort RestartApplication()
auf, direkt nach dem Setzen von PairingStatus - die Fehlermeldung konnte
nie gerendert werden, und wurde auch nirgends geloggt. Ein Fehlschlag
(falscher/abgelaufener Code, Server nicht erreichbar) wirkte dadurch wie
ein kommentarloser Absturz ohne jede Spur.
- SettingsViewModel loggt den Fehler jetzt über AppLogger und zeigt vor
dem Neustart einen Bestätigungsdialog mit der echten Fehlermeldung an.
- AppBootstrapper.RestartApplication() gibt unter dotnet run/IDE-Debug
(wo ProcessPath auf den dotnet-Host statt die App zeigt) die
ursprünglichen Kommandozeilenargumente beim Neustart mit, statt nur
die dotnet-CLI-Hilfe zu öffnen.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Sync-Settings-Tab: neuer Bereich "Gerät koppeln" (10.3.1), nutzt den
bereits vorhandenen, bisher nirgends verdrahteten SnapshotService.
Ein Gerät erzeugt per CreatePairingCode einen verschlüsselten
DB-Snapshot + Einmal-Code, das zweite Gerät übernimmt per
RedeemPairingCode Datenbank und Sync-Schlüssel. Bestätigungsdialog
vor dem Einlösen, da die lokale Datenbank dabei vollständig ersetzt
wird (alter Stand wird automatisch als Backup gesichert).
- Einstellungen: TabPlacement von Top auf Left umgestellt (vertikale
Liste statt langem horizontalem Balken) und die 13 Tabs in drei
logische Gruppen sortiert (Fachliches / Zeitplanung / System).
- Neuer SettingsTab-Enum ersetzt rohe int-Tab-Indizes bei
MainWindowViewModel.NavigateToSettings/
TimetableViewModel.OnNavigateToSettings. Dabei einen bestehenden Bug
gefunden und mitbehoben: das Zahnrad im Stundenplan öffnete über den
hartcodierten Index 7 tatsächlich "Datenschutz" statt des laut
Kommentar/Tooltip beabsichtigten "Ferien & Feiertage".
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Minimale Liste im Tab "Synchronisation" - Entitaet, Zeitpunkt, welche
Seite ConflictResolver gewaehlt hat, mit "Gesehen"-Aktion. Kein
Feld-Diff fuer v1: die Payloads sind clientseitig verschluesselt, ein
Diff wuerde ohnehin nur rohes JSON zeigen.
Neu EventQueue.MarkReviewed(id) - bisher gab es AddConflict/
GetUnreviewed/ConflictCount, aber keinen Weg, einen Konflikt als
gesehen zu markieren.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Neuer Tab in den Einstellungen: Server-URL, Login, Verbindungstest,
Logout.
- Neu SyncSettingsService (Muster AiSettingsService): Token
AES-256-verschluesselt ueber SyncCrypto mit eigenem, rein lokalem
Schluessel - ersetzt die bisherigen Klartext-Helfer
AppBootstrapper.LoadServerUrl/SaveServerUrl und die unverschluesselte
auth.token-Datei
- Neu SyncAuthService fuer den Login-HTTP-Aufruf gegen /api/auth/login
und den Verbindungstest (unterscheidet erreichbar & angemeldet /
erreichbar aber nicht angemeldet / nicht erreichbar)
- Speichern/Anmelden startet die App neu (AppBootstrapper.
RestartApplication, gleiches Muster wie bei DB-Passwort/AppLock-
Aenderungen) - SyncEngine/SnapshotService werden nur einmalig beim
Start registriert, es gibt keinen Live-Re-Registrierungspfad
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
KI-Unterstützung: neuer Einstellungen-Tab (Anmeldung, Guthaben) und Button im
Planungs-Tab, der Einheiten+Stunden als JSON an ein neues PHP-Backend (ai-backend/)
sendet und die Antwort als prüfbare Vorschlagsliste zurückbringt. Provider-Aufruf,
Guthabenverwaltung und Abrechnung nach echten Token-Kosten laufen serverseitig, der
Desktop-Client sieht nie einen LLM-API-Key. Zentral abgesichert: eine von der KI
zurückgegebene Stunden-Id, die zu keiner echten Lesson der Einheit passt, wird nie
als Update übernommen, sondern immer als neue Stunde behandelt.
Kompetenzkatalog-Import (8.1.2): JSON-Export/Import für Kompetenzkataloge.
- 4.4.3: Box "ANSTEHENDE KLAUSUREN" im Heute-Tab, gruppenübergreifend, nächste 21 Tage.
IExamRepository um GetAll() erweitert.
- Nutzer-Feedback: "Vertretung eintragen" deckt auch Ausfall/Sondereinsatz ab, daher
umbenannt in "Ausnahme eintragen". "Stundenplan bearbeiten" (redundant zum Bearbeiten-Tab)
ersetzt durch Zahnrad-Button, der direkt in die Einstellungen springt.
Stunden serienweise aus dem Stundenplan erzeugen (4.2.5); Stundenraster
(Uhrzeiten je Stunde) in den Einstellungen mit Zeitbedarf-Rückmeldung im
Verlaufsplan-Editor; wiederkehrende Pausenaufsicht; neuer "Vertretung
eintragen"-Dialog für einmalige Vertretungsaufsicht, Vertretungsstunde,
Sondereinsätze (Ausflüge, Berufsmessen) und schlichten Stundenausfall.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Neuer Stundenplan mit "Heute"-Standardansicht (Tagesliste unten angedockt,
gruppenübergreifendes Wochenraster mit Fach/Klasse/Raum/Thema, Vor-/Zurück-
Navigation zwischen Kalenderwochen) und separatem Bearbeiten-Raster für die
wöchentliche Zuordnung. Badges für Ferien-/Klausur-Nähe und ausgegraute
Ferientage direkt im Plan statt einer separaten Liste. Ferien-/Feiertage-
Pflege (Bundesland, Schulferien) sitzt jetzt in den Einstellungen statt im
Stundenplan selbst.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Neuer Tab "Planung" in GroupDetailView ersetzt den Platzhalter: Einheiten anlegen/bearbeiten/
als Vorlage in andere Gruppe kopieren, Stunden je Einheit mit Verschieben (inkl. Nachrücken
der Folgestunden). Stundeneditor als tabellarischer Verlaufsplan (Phase/Dauer/Tätigkeit/
Material/Kurzsymbol je Zeile, Uhrzeit aus optionalem Stundenbeginn abgeleitet) statt eines
einzelnen Phase-Felds mit Methoden-/Materialien-Chips — Kurzsymbol als Freitext mit
Vorschlägen aus neuem Kürzel-Katalog (Einstellungen) plus bisher verwendeten Werten.
Schema-Migrationen v1-v3 überführen bestehende Daten verlustfrei. 4.2.5 bewusst offen
gelassen (hängt an Stundenplan, Kapitel 4.3).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Dokumentationseinträge mit Typwahl (Gespräch, Vorkommnis, Förderplan,
Fehlzeit, Elternanruf, Elternbrief), vertrauliche Einträge nur nach
Bestätigung sichtbar, weiche Löschung mit Nachvollziehbarkeit. Fehlzeiten
als Auswertung des bestehenden Anwesenheits-Trackings statt zweiter
Erfassung, mit Schwellenwert-Warnung im Schülerdetail und Dashboard.
Förderplan-Wiedervorlage als Dashboard-Karte. Datenschutz: Löschfristen
mit manueller Bereinigung und DSGVO-Art.-15-Datenauskunft als Export.
Auf Nutzer-Feedback hin ergänzt: Elternanruf mit begleitendem
Gesprächsprotokoll-Dialog (Punkte abhaken, Eindrücke festhalten),
Elternbrief mit Versand-/Rückmeldungs-Tracking, Datei-Anhänge über
LiteDBs Dateispeicher, frei vergebbare Labels zur Nachverfolgung mit
Dringlichkeits-Farbcodierung, sowie eine sichtbare Farblegende für das
bestehende Notenentwicklungs-Diagramm. Dabei einen Absturz behoben:
leere Textfelder lieferten über das Binding null statt "", was beim
Speichern eine NullReferenceException auslöste.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Automatisches rollierendes Backup der Datenbank beim Start mit
Wiederherstellung über die Einstellungen, versionierte Schema-Migration,
optionale Passwort-Verschlüsselung der LiteDB-Datei und eine App-Sperre
nach Inaktivität mit eigenem Passwort.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Zentrale Exception-Behandlung (Dispatcher.UIThread.UnhandledException,
AppDomain, TaskScheduler) verhindert Abstürze und protokolliert Fehler
über AppLogger in eine rotierende Log-Datei im App-Datenverzeichnis.
Toast-Benachrichtigungen zeigen Erfolg/Fehler global an. Alle Dialoge
mit Formularfeldern zeigen Validierungsmeldungen jetzt direkt am
betroffenen Feld statt in einem Sammel-Label.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Notenübersicht der Gruppe (Matrix, Gesamt-Spalte, Sortierung, Halbjahresfilter),
Einzelnoten-Pflege samt Sammelerfassung, Gewichtungsschema mit Voreinstellung je
Gruppentyp, Zeugnisnoten-Berechnung mit Übersteuern/Festschreiben/Export und
Notenentwicklung im Schülerdetail.
Dazu Anwesenheits-/Hausaufgaben-Tracking je Mitarbeit-Sitzung, ein neuer
Mitarbeits-Assistent (Zeitleiste mit Abschnitten, automatischer Notenvorschlag,
Zusammenzug zur Halbjahresnote) und eine Dashboard-Kachel für offene
Entschuldigungen. Außerdem: verbliebene englische Begriffe in Auswahlfeldern
und Buttons auf Deutsch umgestellt.
- Notenschlüssel-Editor im ExamDialog: Stufen (Note/Prozentgrenze)
bearbeitbar, Vorbelegung passend zum GradingSystem der Gruppe,
Live-Anzeige der absoluten Punktegrenze je Stufe, Validierung
(lückenlos, keine Dopplungen) über GradingService.ValidateGradingKey.
- Neues Modell GradingKeyTemplate + Repository: Notenschlüssel als
Vorlage speichern/anwenden, direkt aus dem ExamDialog heraus.
- Einstellungen: Fächer / Kompetenzen / Notenschlüssel-Vorlagen sind
jetzt eigene Tabs statt einer gemeinsam wachsenden Liste. Vorlagen
zeigen nur noch eine kompakte Zeile; die Stufen-Bearbeitung läuft
über ein Popup-Fenster (GradingKeyTemplateDialog).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>