message_bubble.dart war vollständig unbenutzt (durch message_group.dart abgelöst). Die zwei identischen _formatTime-Methoden in message_group.dart zu einer Top-Level-Funktion zusammengeführt - reine Extraktion, keine Verhaltensänderung. flutter analyze bleibt sauber.
23 KiB
Pyramid – Arbeitsprotokoll
Neueste Einträge OBEN. Jede Claude-Session schreibt hier nach jedem abgeschlossenen Schritt (und beim Abbruch mitten im Schritt den Zwischenstand). Format:
## JJJJ-MM-TT – Kurztitel
**Erledigt:** was fertig ist (mit Commit-Hash)
**Offen/Nächster Schritt:** der konkrete nächste Handgriff
**Stolperfallen:** was schiefging und wie es gelöst wurde (damit es nie zweimal passiert)
**Fragen an Bernd:** (optional) gesammelte Richtungsfragen, die nicht blockieren
2026-07-03 – M2: Toten Code & Duplikate entfernt (Chat-Timeline)
Erledigt: Vorgriff auf den ROADMAP-Punkt „Toten Code & Duplikate entfernen" (technisch der 5. Punkt in M2, aber risikofrei und ohne GUI testbar – im Gegensatz zum aktuell blockierten „Call-Schicht entwirren", siehe Frage an Bernd im Eintrag darunter):
lib/features/chat/message_bubble.dart(178 Zeilen) gelöscht – vollständig toter Code, wurde nirgends importiert/instanziiert (durchmessage_group.dartabgelöst), pergrepdoppelt bestätigt.- Die zwei identischen
_formatTime-Methoden inmessage_group.dart(_MessageGroupStateZeile 322,_ContinuationMessageStateZeile 475 – Vorher-Zeilennummern) zu einer gemeinsamen Top-Level-Funktion_formatMessageTime()zusammengeführt, beide Aufrufstellen umgestellt. Reine Extraktion, keine Verhaltensänderung (identischer Code vorher/nachher).pinned_messages_panel.dart:_formatTimebewusst NICHT angefasst – hat andere Logik (relatives Datum „vor Xd"), ist kein echtes Duplikat. flutter analyzeweiterhin sauber: nur der eine bekannte, bewusst zurückgestellte Hinweis (chat_provider.dart:42,Timeline.onUpdatedeprecated, hängt am E2EE-Redecrypt-Pfad, siehe M0-Eintrag).
Offen/Nächster Schritt: UNGETESTET (Pi) im Sinne von „nicht in echter UI gesehen" – kein GUI auf diesem Pi verfügbar. Da es sich aber um reine Code-Verschiebung ohne Logikänderung handelt (identischer Funktionskörper), ist das Risiko gering; trotzdem beim nächsten Windows-Lauf kurz einen Chat mit mehreren aufeinanderfolgenden Nachrichten (Zeit-Anzeige) und eine Fortsetzungsnachricht (Hover zeigt Uhrzeit) ansehen.
Stolperfallen: Keine.
2026-07-03 – M2: Modul-Schnitt definiert (docs/M2_MODULE_SCHNITT.md)
Erledigt: Ausgehend von der Ist-Analyse (Eintrag darunter) die konkreten
Modul-Grenzen + öffentliche Schnittstellen entworfen, dokumentiert in
docs/M2_MODULE_SCHNITT.md. Reine Planung, kein Code geändert. Wichtigste
Erkenntnis beim genaueren Lesen von voip_manager.dart und
livekit_call_manager.dart: „Calls" ist architektonisch kein einzelnes
Feature, sondern zwei unabhängige Mechanismen, die getrennt bleiben sollten:
PyramidVoipManager= natives Matrix-1:1-VoIP (m.call.*, direkte WebRTC-Peer-Connection, kein SFU)LiveKitCallManager= SFU-basierte Voice-Channels (LiveKit-Raum, Presence via Matrix-State-Event, Screensharing, Mehrpersonen) – das ist der Discord-artige Kanal aus M3/M4
Modul-Liste im Dokument: call_signaling, voice_channel, call_ui,
settings (aufgesplittet in Sektionsdateien), verification (neu, aus
Settings herausgelöst – SAS/QR/Recovery-Key), storage (Ausbau der
bestehenden settings_prefs.dart-Abstraktion zur Pflicht), auth (schon
relativ sauber, kein akuter Bedarf), push (schon getrennt, eigener
sqflite-Zugriff in background_push.dart ist bewusst so, kein
Refactoring-Kandidat), chat_timeline/rooms (niedrigste Priorität, da
strukturell am wenigsten verwoben – Hauptproblem dort ist Dateigröße/Duplikate,
nicht Kopplung). Jeweils mit Dart-Interface-Skizze bzw. Datei-Zielliste.
Empfohlene Umsetzungsreihenfolge: 1) Call-Pilot (call_signaling +
voice_channel + call_ui, deckt gleich zwei ROADMAP-Punkte ab), 2)
settings_modal.dart aufsplitten (geringes Risiko, reine Datei-Teilung),
3) verification herauslösen, 4) storage-Fassade schrittweise erzwingen,
5) chat_timeline/rooms zuletzt.
Offen/Nächster Schritt: Wartet auf Bernds Entscheidung, ob der Call-Pilot wie vorgeschlagen als Nächstes umgesetzt wird (siehe Frage unten). Erst danach den ROADMAP-Punkt „Call-Schicht entwirren" wirklich anfassen – das ist die erste Stelle mit echtem Verhaltensrisiko in M2 (CLAUDE.md: nach Refactoring- Schritten immer App starten + Kernflows prüfen, hier zusätzlich brisant, weil GUI-Test auf dem Pi nicht möglich ist).
Stolperfallen: Der erste Ist-Analyse-Durchgang (Subagent) hatte einen
falschen Befund (rooms_provider.dart-Import in app_state.dart sei toter
Code) – beim genaueren Lesen für den Modul-Schnitt widerlegt
(voiceParticipantsProvider nutzt roomListProvider daraus). Bereits im
Ist-Analyse-Eintrag korrigiert. Lehre: Subagent-Ist-Analysen sind ein guter
Startpunkt, aber vor jedem darauf aufbauenden Schritt einzelne Befunde
gegenlesen, nicht blind übernehmen.
Fragen an Bernd:
- Call-Pilot wie in
docs/M2_MODULE_SCHNITT.mdvorgeschlagen (zuerstcall_signaling/voice_channel/call_uientwirren) als nächster Umsetzungsschritt in Ordnung, oder lieber zuerstsettings_modal.dartaufsplitten (geringeres Risiko, aber deckt keinen ROADMAP-Punkt aus M2 direkt ab)? Ohne GUI-Zugriff auf dem Pi kann der riskantere Call-Umbau hier ohnehin nicht praktisch getestet werden – das spricht eher für „auf dem PC anfangen", falls Zeitdruck besteht.
2026-07-03 – M2: Ist-Analyse der Architektur geschrieben
Erledigt: M1 hat aktuell keinen auf dem Pi bearbeitbaren Punkt mehr offen (SQLCipher wartet auf Bernds Priorisierung, Härtetest braucht GUI/PC – siehe Fragen an Bernd unten und Eintrag 2026-07-03 „3 schon vorhanden, 1 echte Lücke"). Deshalb mit M2 weitergemacht, erster Punkt: Ist-Analyse. Per Code-Lektüre (Zeilenzahlen, Import-Graph, grep) folgende Schwachstellen gefunden:
- Gott-Dateien:
widgets/settings_modal.dartmit 5541 Zeilen / 50+ Klassen bündelt mindestens 8 unabhängige Bereiche (Profil, Benachrichtigungen, Voice/TURN, E2EE-Verifizierung inkl. SAS/QR, Sessions, Account, Erscheinungsbild, Updates). Weitere große Dateien:message_group.dart(2780),rooms_panel.dart(2555),space_admin_dialog.dart(2278),chat_view.dart(2116),document_viewer.dart(1773),voice_channel.dart(1123),app_shell.dart(1073). - Call-Schicht unsauber verteilt statt hinter einer Schnittstelle:
core/voip_manager.dart(Matrix-VoIP-Signalisierung),core/livekit_call_manager.dart(LiveKit-Transport),features/call/voice_channel.dart+mini_call_widget.dart(UI) – aberchat_view.dart,matrix_client.dart,settings_modal.dartgreifen alle DIREKT auf die Manager zu statt über eine gemeinsame Call-Fassade. Vier verschiedene Module importierenvoice_channel.dartdirekt. Genau das Gegenteil des „austauschbare Bausteine"-Ziels aus CLAUDE.md. - State-Management gemischt: 2 zentrale
ChangeNotifier-Singletons (voip_manager.dart,livekit_call_manager.dart) statt Riverpod-Notifier, eingebunden überapp_state.dart(callStateProvider,voipStateProvider). Migration sinnvoll, aber riskant wegen breiter Call-Sites und enger SDK-Callback-Kopplung (LiveKit-Room-Events, Matrix-WebRTCDelegate) – sollte zusammen mit der Call-Fassade angegangen werden, nicht isoliert. core/ist nicht rein generisch: importiert Feature-Code direkt (app.dart/router.dart→features/auth/*,matrix_client.dartinstanziiertPyramidVoipManagerdirekt).app_state.dartselbst ist ein Sammelbecken für Theme-, Call-, Voice-, Share-Target- und Spaces-Provider aus praktisch allen Features – zentraler Kopplungspunkt, der jedem Modulschnitt im Weg steht. (Korrektur beim genaueren Hinsehen für den Modul-Schnitt-Punkt: derrooms_provider.dart-Import dort ist entgegen der ersten Vermutung KEIN toter Altlast-Import –voiceParticipantsProvidernutztroomListProviderdaraus. Zeigt: Subagent-Befunde vor dem Weiterbauen selbst nachprüfen.)- Keine gemeinsame Storage-Schnittstelle:
SharedPreferences.getInstance()wird an 12 Stellen direkt aufgerufen, obwohlcore/settings_prefs.dartbereits eineStateNotifier-Abstraktion (BoolPref,StringSetPref) anbietet – wird meist umgangen.sqflitewird zusätzlich unabhängig inbackground_push.dartnochmal geöffnet (eigene DB-Instanz fürs Background-Isolate).media_cache.dartist dagegen sauber gekapselt – gutes Vorbild für die anderen Speicherzugriffe. - Toter Code bestätigt:
features/chat/message_bubble.dart(178 Zeilen, KlasseMessageBubble) wird nirgends instanziiert – vonmessage_group.dartabgelöst, kann beim Refactoring entfernt werden. - Duplikate:
_formatTime/_formatDateunabhängig implementiert inpinned_messages_panel.dart:206,message_group.dart:322UND:475(zwei Mal im selben File!), sowie im totenmessage_bubble.dart:80/165.
Modul-Kandidaten für den nächsten Punkt („Modul-Schnitt definieren"):
call_signaling(Matrix-VoIP) –core/voip_manager.dartcall_transport(LiveKit) –core/livekit_call_manager.dartcall_ui(nur UI, konsumiert 1+2 über Interface) –features/call/*settings/*aufsplitten: profile, encryption_verification, sessions, notifications, appearance, account – auswidgets/settings_modal.dartverificationals eigenständiges Feature (SAS/QR/Recovery-Key), nicht Teil von Settings – wiederverwendbar (z. B. künftig beim Login)storage– gemeinsame Fassade,settings_prefs.dartals Pflichtzugang statt 12 Direktzugriffsstellenapp_state.dartauflösen in feature-lokale Provider-Dateienchat_timeline–message_group.dart+pinned_messages_panel.dart, dabei toten Code (message_bubble.dart) entfernen,_formatTime/_formatDateinchat/format_utils.dartzusammenführen
Offen/Nächster Schritt: M2, zweiter Punkt – „Modul-Schnitt definieren":
aus der obigen Kandidatenliste konkrete Modul-Interfaces (Dart-Abstract-Classes
o. ä.) entwerfen, dann EIN Modul zuerst umbauen (Vorschlag: call_*, da am
klarsten abgegrenzt und am dringendsten laut CLAUDE.md-Leitprinzip) als Pilot,
bevor der Rest folgt. Kein Codeumbau in diesem Schritt, nur Schnittstellen-Design.
Stolperfallen: Keine – reine Lesearbeit, kein Risiko für Bestandsdaten. Analyse wurde von einem Explore-Subagent erstellt und stichprobenartig plausibilisiert (Zeilenzahlen/Imports selbst nachgezählt), nicht jede Einzelbehauptung im Detail nachverifiziert.
Fragen an Bernd:
- SQLCipher-Priorität weiterhin offen (siehe Eintrag „3 schon vorhanden, 1 echte Lücke" weiter unten) – blockiert nicht, aber ohne Antwort bleibt der M1-Punkt bis zum nächsten PC-Praxistest liegen.
- Für M2: Soll ich die Call-Schicht als erstes Pilot-Modul umbauen (mein
Vorschlag oben), oder hast du eine andere Präferenz (z. B. erst die
settings_modal.dartaufsplitten, weil die am unübersichtlichsten ist)?
2026-07-03 – M1: Restliche Punkte geprüft – 3 schon vorhanden, 1 echte Lücke gefunden
Erledigt:
- Logout-Warnung bei fehlendem Key-Backup (Commit
b5762ea): neue FunktionisKeyBackupMissing(client)inbootstrap_dialog.dart(prüft Cross-Signing +keyManager.isCached()). Beide Logout-Dialoge insettings_modal.dartzeigen jetzt eine rote Klartext-Warnung statt des neutralen Textes, wenn kein Backup eingerichtet ist. - Drei ROADMAP-Punkte waren bereits umgesetzt (nur nicht abgehakt) – durch
Code-Lektüre verifiziert, nicht neu gebaut:
- Key-Backup einrichten/wiederherstellen:
bootstrap_dialog.dartdeckt beides über denBootstrap-Zustandsautomaten des matrix-SDK ab (askNewSsssfür Neueinrichtung,askUnlockSsssfragt auf einem neuen Gerät nach dem Recovery-Key). Wird automatisch getriggert, wenn Cross-Signing fehlt (app_shell.dart:_triggerBootstrap). - Geräte-/Sessionverwaltung:
_SessionsSectioninsettings_modal.dart– Liste, Umbenennen, SAS/QR-Geräteverifizierung, Einzel- und Massen-Abmeldung (mit Passwort-Reauth bei UIA-Anforderung).
- Key-Backup einrichten/wiederherstellen:
- Echte Sicherheitslücke gefunden:
sqlcipher_flutter_libsist eine Abhängigkeit inpubspec.yaml, wird aber nirgends im Code benutzt.matrix_client.dart(Haupt-App) undbackground_push.dart(Push-Hintergrund) öffnenpyramid.sqlitebeide über den normalen, unverschlüsseltensqflite/sqflite_common_ffi-Factory. Die Krypto-DB (Access-Token, gepickelter Olm-Account, Megolm-Sessions, komplette Nachrichtenhistorie) liegt also im Klartext auf der Platte – nur durch Androids App-Sandbox geschützt, nicht durch eine eigene Verschlüsselung.
Offen/Nächster Schritt: SQLCipher-Anbindung NICHT blind auf dem Pi umgesetzt – siehe Stolperfalle unten. Braucht einen eigenen, vorsichtig geplanten PC-Termin: Backup der Test-DB, Migrationscode (bestehende Klartext-DB einmalig nach SQLCipher überführen), Test auf einem Gerät mit echten Daten, erst dann Rollout.
Fragen an Bernd:
- Priorität der SQLCipher-Lücke: Soll das vor M2 (Refactoring) angegangen werden, oder reicht die App-Sandbox als Schutz erstmal aus (Angreifer bräuchte Root oder physischen Zugriff + ADB, um die Datei überhaupt zu lesen)? Die Migration bestehender Installationen (Uta!) ist der aufwändige/riskante Teil, nicht die Verschlüsselung selbst.
Stolperfallen:
- Eine DB-Verschlüsselungs-Migration ist genau die Art Änderung, die laut CLAUDE.md nicht "mal eben" auf dem Pi ohne Testgerät gemacht werden darf: scheitert die Migration (falscher Schlüssel, falsche PRAGMA-Reihenfolge, Timing zwischen Haupt-App und Push-Hintergrund-Client), sind Utas Nachrichten und Krypto-Schlüssel unwiederbringlich weg. Deshalb hier nur dokumentiert, nicht implementiert.
2026-07-03 – M1: Push-Regression vermutlich dieselbe Ursache wie Random-Logout
Erledigt: Vor dem Blick in den Push-Code die Vermutung geprüft, ob die Push-Entschlüsselungs-Regression und der Uta-Random-Logout-Bug (siehe Eintrag weiter unten) zusammenhängen – Ergebnis: sehr wahrscheinlich ja, exakt dieselbe Ursache.
client.getEventByPushNotification(...)(aufgerufen in_bgDecryptAndShow,background_push.dart:84) ruft als ALLERERSTESensureNotSoftLoggedOut()auf (matrix-Paketclient.dart:1878). Diese Funktion prüft, ob der Access-Token in < 1 Minute abläuft, und löst dann_handleSoftLogout()aus — dieselbe Funktion, die ohne Refresh-Token (unser Zustand vor Commit9dc83f7) sofort einen echtenclient.logout()auslöst (siehe Eintrag unten).- Der Hintergrund-Client aus
_buildClient()liest dieselbepyramid.sqlitewie der Haupt-Client. Einlogout()/clear()aus dem Hintergrund-Isolat würde also die komplette Session (inkl. Krypto-Schlüssel) für die GESAMTE App zerstören – nicht nur für den einen Push. Das erklärt, warum das Problem als dauerhafte Regression erscheint ("seit dem letzten Update nie wieder"): Nach dem ersten Auto-Logout-Ereignis (ausgelöst beim Sync ODER beim Entschlüsseln eines Pushs) sind die Schlüssel weg, jede folgende Entschlüsselung schlägt fehl →BgEnginezeigt nur noch den „Neue Nachricht"-Platzhalter (Fallback nach 6 s), nie mehr den echten Text. - Der bereits committete Fix (
refreshToken: truebeim Login,9dc83f7) behebt damit vermutlich BEIDE Symptome gleichzeitig: der Refresh-Token liegt in der gemeinsamen DB, also kann auch der Hintergrund-Client ihn lesen und einen drohenden Soft-Logout durch stillen Refresh abwenden, statt die Session zu zerstören.
Offen/Nächster Schritt: Gehört zum selben Praxistest wie der
Random-Logout-Punkt oben – zusätzlich beobachten, ob nach einer Weile
(mehrere Stunden/Tage) echte Push-Inhalte statt Platzhalter ankommen. Schlägt
das fehl, liegt eine zweite, unabhängige Ursache vor (dann docs/NOTIFICATIONS.md
- Memory „Pyramid Push" erneut konsultieren, insbesondere die 3 dort gelisteten Fallstricke der Hintergrund-Entschlüsselung).
Stolperfallen: Diese Verbindung wurde rein durch Lesen des matrix-SDK-
Quellcodes hergeleitet (~/.pub-cache/hosted/pub.dev/matrix-6.2.0/lib/src/client.dart),
nicht durch Beobachtung auf einem echten Gerät – bewusst als Vermutung
markiert, bis der PC-Praxistest sie bestätigt.
2026-07-03 – M1: Uta-Random-Logout – Ursache gefunden + Fix (UNGETESTET/Pi)
Erledigt:
- Alle Logout-Auslöser im Code kartiert:
- 3 bewusste Nutzer-Logout-Buttons in
settings_modal.dart(alle hinter Bestätigungsdialog) – kein Kandidat für "random" - Der eigentliche Verdächtige:
matrix-Paket (v6.2.0)Client._innerSync()behandeltM_UNKNOWN_TOKENvom/sync-Endpunkt so: beisoft_logout: true→_handleSoftLogout()→ versuchtrefreshAccessToken()→ das SDK hatte nie einen Refresh-Token angefordert (client.login(...)inlogin_notifier.dartrief ohnerefreshToken: trueauf) →refreshAccessToken()wirft sofort "No refresh token available" → Catch-Block ruftawait logout()auf: ein echter, destruktiver Logout, ausgelöst rein durch einen normalen Soft-Logout (z. B. abgelaufenes Access-Token), ganz ohne Nutzerinteraktion. Quelle:~/.pub-cache/hosted/pub.dev/matrix-6.2.0/lib/src/client.dart:2374-2384und:2496-2509.
- 3 bewusste Nutzer-Logout-Buttons in
- Logging (Commit
63e4919): neuelib/core/auth_log.dartschreibt jeden Login-Status-Wechsel (client.onLoginStateChanged) sowie SDK-Warnungen/-Fehler (Logs().onLog) inauth_log.txtim App-Support-Verzeichnis – übersteht App-Neustart. Zusätzlich loggen alle 3 Nutzer-Logout-Buttons sich selbst, damit sich künftig unterscheiden lässt: Nutzer-Logout vs. SDK-Auto-Logout. Reine Zusatzfunktion, keine Verhaltensänderung. - Fix (Commit
9dc83f7):client.login(...)fordert jetztrefreshToken: truean. Damit kann das SDK einen Soft-Logout künftig durch stillen Token-Refresh überstehen, statt die Sitzung zu zerstören. Unterstützt der Server keine Refresh-Tokens, bleibt das Verhalten exakt wie vorher (response.refreshTokenist dannnull) – der Fix kann also nichts verschlimmern.
Offen/Nächster Schritt:
- Praxistest auf dem PC (zwingend vor Haken in ROADMAP!): Login → Nachrichten
senden/lesen → Logout → erneuter Login → alte verschlüsselte Nachrichten noch
lesbar? Dabei prüfen, ob
auth_log.txt(App-Support-Verzeichnis) die Login-Status-Wechsel sauber mitschreibt. - Danach: den nächsten Punkt in M1 angehen (Push-Entschlüsselungs-Regression).
- Wichtig für Bernd/Uta: Der Fix wirkt nur für NEUE Logins. Utas bereits bestehende Sitzung bekommt erst nach einem einmaligen manuellen Neu-Login einen Refresh-Token und ist bis dahin weiterhin anfällig. Sobald der PC-Test grün ist, sollte Uta sich einmal aus- und wieder einloggen.
Stolperfallen:
- Konnte auf dem Pi nicht mit echtem Login/Logout getestet werden (kein GUI, kein Matrix-Testaccount zur Hand) – Fix beruht auf genauem Lesen des matrix-SDK-Quellcodes, nicht auf Beobachtung im Betrieb. Deshalb zwingend vor dem nächsten Haken in ROADMAP am PC nachprüfen.
chat_provider.dart:42nutzt weiterhin das deprecatedTimeline.onUpdate(Re-Entschlüsseln nach Schlüssel-Empfang) – hängt mit demselben Sync-Bereich zusammen, aber bewusst nicht angefasst, um nicht zwei riskante Änderungen im selben Bereich gleichzeitig ungetestet zu committen.
2026-07-03 – M0 abgeschlossen: Ordnung, flutter analyze sauber, README
Erledigt:
- Liegen gebliebene Deprecation-Fixes aus einer abgebrochenen Session committet
(
withOpacity→withValues,activeColor→activeThumbColor,cacheExtent→ScrollCacheExtent,PublicRoomsChunk→PublishedRoomsChunk) – Commit057ac1e - Restliche
flutter analyze-Hinweise behoben – Commit401bd6a:document_viewer.dart:Matrix4.translate/scale→translateByDouble/scaleByDouble(PDF-Zoom, gleiches Verhalten)rooms_panel.dart:onReorder→onReorderItem(Index-Korrektur jetzt intern, manuellesnewIdx--entfernt);implementation_imports-Hinweis kommentiert (SpaceChild wird vommatrix-Paket nicht öffentlich exportiert, kein Fix möglich)voip_manager.dart:getSources()-Override kommentiert (Pflicht-Override der abstraktenMediaDevices-Klasse, die die Methode selbst deprecated hat)settings_modal.dart: zweiBuildContext-nach-await-Stellen mitcontext.mountedabgesichert (Geräte umbenennen, Passwortabfrage bei Massenlogout)- Bewusst NICHT gefixt:
chat_provider.dart:42(Timeline.onUpdatedeprecated, Ersatz wäreclient.onSync+ Raum-Filter). Hängt am E2EE-Redecrypt-Pfad (Re-Entschlüsseln nach Schlüssel-Empfang) – laut CLAUDE.md heiliger Bereich, Umbau nur mit dediziertem Login→Nachrichten→Logout→Login-Test, nicht nebenbei.
lib/features/calls/(Leiche) geprüft: existiert nicht mehr, nurlib/features/call/mit den echten Dateien – Punkt war bereits erledigt, nur nicht abgehakt.- README.md durch echte Projektbeschreibung ersetzt (Funktionsumfang, Build, Struktur) – Commit
74d38fd - ROADMAP.md: M0 komplett abgehakt.
Offen/Nächster Schritt: M1, erster Punkt – Uta-Random-Logout-Bug untersuchen
(Logging an allen Logout-Pfaden einbauen, dann Ursache finden). Direkt danach die
Push-Entschlüsselungs-Regression (docs/NOTIFICATIONS.md + Memory „Pyramid Push"
vorher lesen).
Stolperfallen:
- Kein
test/-Ordner vorhanden →flutter testläuft ins Leere, keine automatisierte Absicherung.flutter analyzelief sauber (0 Fehler/Warnungen), aber die Lint-Fixes indocument_viewer.dart(PDF-Zoom) undrooms_panel.dart(Drag-Reorder der Raumliste) sind UNGETESTET in echter UI – nächster Windows-Lauf sollte kurz PDF-Zoom und Raum-Umsortieren per Drag prüfen. - Der
ignore:-Kommentar für einen deprecated-Aufruf muss auf der Zeile unmittelbar über der betroffenen Codezeile stehen, nicht nur "in der Nähe" – sonst wirkt er nicht (beivoip_manager.darterst falsch über@overridegesetzt, dann korrigiert).
2026-07-03 – Arbeitsstruktur angelegt + Vollbackup (Setup, noch kein Code)
Erledigt:
- Vollbackup inkl. Git-Historie:
MatrixPi\backups\pyramid-kopie_backup_2026-07-03.tar.gz(510 MB) CLAUDE.md(Arbeitsregeln),ROADMAP.md(M0–M7 nach Bernds Prioritäten), dieses Protokoll- Klargestellt:
C:\Users\nordm\pyramid - Kopieist das EINZIGE aktuelle Repo;C:\Users\nordm\pyramidundMatrixPi\pyramidsind veraltete April-Stände (Commitc9af913)
Offen/Nächster Schritt: M0, Punkt 2 – die ~140 uncommitteten Dateien mit git status
sichten und in thematische Commits aufteilen (diese drei neuen Dateien mit committen),
dann git push origin master.
Stolperfallen:
- Letzter Commit ist vom 2026-04-28 (
d706ace), gearbeitet wurde aber bis mindestens 2026-06-12 → zwischen Commits und Realität liegen 6 Wochen. Genau deshalb: ab jetzt kleine Commits nach jedem Schritt. - Git-Remote (Gitea auf dem Pi) enthält Zugangsdaten in der URL – funktioniert, aber nur erreichbar, wenn der Pi läuft (unterwegs: WireGuard nötig).