Secretary

Apps/journal/changelog
Login

Apps/journal/changelog

Secretary Journal (Android) - Changelog

Every released version of the Secretary Journal app, newest first.

App documentation: Apps/journal

Status

Status 2026-10-01 (143)

Secretary Journal 143 (versionCode 143): die Sync-Aktion ist ohne Konto weg, Passwortfelder zeigen Klartext. Beides sitzt im gemeinsamen Code und trifft damit alle acht Clients.

(1) Keine Sync-Aktion ohne Konto. AppHeader (Kit.kt) blendet die Sync-Aktion bereits aus, wenn onSync null ist - das war die vorhandene Konvention, nur wurde sie an keiner Stelle benutzt. OfflineBanner (StatusBanners.kt) verlangte dagegen einen nicht-nullbaren onSync und zeichnete den Refresh-Button bedingungslos; der Parameter ist jetzt (() -> Unit)?, und ohne Konto fehlt der Knopf (die Meldung "offline" bleibt stehen). Alle Aufrufstellen reichen den Callback nur noch durch, wenn wirklich ein Konto existiert: loggedIn der jeweiligen ViewModel, im Kalender der collected isLoggedIn-StateFlow. Das Journal ist der einzige Client, bei dem das sichtbar war - es hat keine Login-Sperre und laeuft im lokalen Modus (localMode = !repo.isConfigured()) ohne Konto weiter, zeigte den Sync-Knopf aber trotzdem. Beim Secrets-Tresor war der Knopf vorhanden und nur deaktiviert (enabled = state.connected); er wird jetzt gar nicht erst gezeichnet, der Spinner waehrend state.syncing bleibt. Am Launcher aendert sich nichts: die Server-Sync-Sektion im Settings-Screen war schon an account != null gehaengt.

(2) Passwortfelder zeigen Klartext. Alle Eingabefelder fuer Passwoerter nehmen VisualTransformation.None; die Tastatur bleibt KeyboardType.Password. Betroffen sind der gemeinsame Login-Screen (SecretaryLoginScreen), die Journal-Passwortdialoge (PasswordDialogs: Setzen, Aendern, Abfragen) und das Entschperren (UnlockScreen) sowie im Tresor die Felder fuer Recovery-Passphrase, Entschperr-Passphrase, KDBX-Import und KDBX-Export (SecretsApp) und das Passwortfeld im Eintrags-Editor (Browse). Anlass war die Darstellung, nicht die Sicherheit: die Maske besteht aus U+25CF (●), und die gebundelte Typewriter-Schrift Special Elite deckt dieses Zeichen nicht ab - die Felder zeigten unlesbare Ersatzglyphen. In den Tresor-Dialogen ist der Sichtbarkeits-Umschalter damit ueberfluessig und mit ihm die Felder passwordVisible/visible, der Eye-Button bzw. der Textbutton Anzeigen/Verbergen und die Visibility/VisibilityOff-Imports weg. Der Reveal-Pfad fuer gespeicherte Secrets in Browse (FieldRow) bleibt unberuehrt: das ist eine Anzeige, keine Eingabe.

Tests: keine neuen, kein JVM-Verhalten geaendert. 662 Tests gruen (Kalender 55, common 100, Kontakte 44, Launcher 12, Secrets 405, Tasks 46), verifiziert ueber gradle test; alle neun Module kompilieren (compileDebugKotlin, offline), und die Neuuebersetzung meldet in keiner der geaenderten Dateien eine Warnung. Das Journal ist der Client, bei dem (1) ohne Konto wirklich sichtbar war - kein Login-Gate, lokaler Modus. versionCode 142 -> 143.

Status 2026-09-30 (142)

Secretary Journal 142 (versionCode 142): Gewohnheiten-Typ fehlte im Tutorial (SRS 1.9.0, FR-J-120).

Der Einstiegstyp EntryType.HABIT kam in v130 mit allem drum und dran (Editor, FAB, Kalender, Klartext-Bericht, Vorlagen, gesammelte Texte) — die pages-Liste in TutorialScreen.kt wurde dabei aber nicht mitgezogen und endete beim Skill. Das Tutorial war damit unvollstaendig, obwohl tutorial_types_body "alle Eintragstypen" verspricht und tutorial_gathered_body die Gewohnheiten schon nennt. Neu ist eine Gewohnheiten-Seite hinter der Skill-Seite, damit die Reihenfolge der EntryType.entries (HABIT steht dort am Ende) erhalten bleibt: Icons.Filled.Checklist (derselbe Icon wie in JournalTypeUi), tutorial_habit_title/tutorial_habit_body DE+EN, und TutorialTry.HABIT als neue Enum-Konstante. Der "Ausprobieren"-Knopf darauf braucht die when-Verzweigung im NavGraph, sonst waere die Seite nur Text — sie verdrahtet vm.openHabitEntryForDate(LocalDate.now()), also den vorausgefuellten Gewohnheiten-Editor, wie die anderen Typen. tutorial_types_body sagt jetzt "Gewohnheiten und Skills" statt nur "Skills". Das Tutorial hat damit 16 Seiten (vorher 15), der Seitenzaehler (tutorial_page_cd) und die Punkteanzeiige zaehlen die Liste automatisch mit. Der KDoc am Screen vermerkt nun ausdruecklich, dass ein neuer Einstiegstyp hier eine Seite braucht — genau die Luecke, die v130 aufgerissen hat. SRS 1.9.0.

versionCode 141 -> 142. CONTEXT.md updated.

Status 2026-09-30 (141)

Secretary Journal 141 (versionCode 141): Gesammelte Medikamenten als Kombination + alle Felder gleich behandelt (SRS 1.8.0, FR-J-112/113/114).

(1) Medikamenten-Kombination wird gesammelt. Bisher standen im Gathered-Screen zwei getrennte Zeilen fuer Wirkstoff und Staerke — die Kombination, also was tatsaechlich eingenommen wurde, gar nicht. Neu ist das abgeleitete GatherField.MEDICINE_COMBINATION: medicineCombination verknuepft den Wirkstoff mit der Dosis ("Ibuprofen 400 mg", ohne Dosis degeneriert es zum reinen Wirkstoff, ohne Stoff greift es auf einen Legacy- Namen zurueck). Das ist die einzige abgeleitete GatherField – sie hat kein Editor-Feld, gatheredTextOf liest sie, und withGatheredText verweigert sie mit error("MEDICINE_COMBINATION is derived - split it with withRenamedGatheredText"), statt still eine der beiden Haelften zu treffen. Ein Umbenennen oder Zusammenfuehren dieser Zeile schreibt deshalb beide Felder zurueck: das neue JournalViewModel .withRenamedMedicineCombination schneidet am ersten Leerzeichen (substringBefore/substringAfter), ein Eintrag ohne Dosis behaelt eine leere Dosis, und ein medicineName, der den Wirkstoff spiegelt, wandert mit (medicineName == medicineSubstance || == old vor dem Leerzeichen), ein abweichender Legacy-Name bleibt stehen. gatheredTexts() fuehrt nun statt der Sonderregel pro-medizin ein emitted-Set: der Name wird weiterhin zugunsten des Wirkstoffs verworfen (v57-Spiegelung), und sonst wird kein Text zweimal fuer denselben Eintrag gelistet — ohne Dose also kein zweites "Ibuprofen" aus der Kombination. gatherFields fuehrt die Kombination zwischen Wirkstoff und Staerke. ProposalEngine.scanRecurringPatterns sieht sie automatisch mit, der Ausloeser-/Skill-Editor filtert weiterhin auf field == TEXT.

(2) Die Feld-Labels sind weg. Die Meta-Zeile zeigte je Wert das Editor-Feld ("Highlight 1/2/3", "Wirkstoff", "Staerke", ...), also war gerade die Highlight-Liste sichtbar nach Feld sortiert und jeder Typ anders behandelt. GatheredScreen rendert jetzt ueber alle Felder eines Typs gleich: nur noch der Text plus gathered_meta (n× · Datum) und optional der Ø-Abstand aus scanRecurringPatterns. Der showField-Parameter und JournalTypeUi.gatherFieldLabel sind entfallen, die neun gathered_field_*-Strings in DE+EN mit. Das Zusammenfuehren bleibt feld-skaliert — das Zielmenue listet weiter nur Werte desselben Feldes (items.filter { it.field == item.field && ... }), ein Wirkstoff laesst sich also weiterhin nicht in eine Dosis fuehren; genau das war mit FR-J-113 (High) gemeint. Die Sortierung bleibt count absteigend mit entryType/field/text als Tiebreak, das Label war ohnehin nur Deko. SRS 1.8.0.

versionCode 140 -> 141. CONTEXT.md updated.

Status 2026-09-30 (140)

Secretary Journal 140 (versionCode 140): Gesammelte Texte statt "Gesammelte Trigger & Skills" – der Screen sammelt jetzt jeden Freitext aus **jedem Eintragstyp; die Einstellungs-Sektion heisst nicht mehr "Datenschutz", sondern "Verbergen"**.

(1) GatherEngine über alle Eintragstypen (SRS 4.12, FR-J-112/113). Die compute-Filterung auf TRIGGER/SKILL ist entfernt: GatherEngine sammelt jetzt über JournalEntry.gatheredTexts() jedes nicht-leere Textfeld eines Eintrags – Highlights (3 Felder), Medikament (Name, Wirkstoff, Stärke, Grund), Essen (Beschreibung) bzw. Getränk (Name), Trigger, Skill und Gewohnheit (text). Damit ein Wert eindeutig bleibt und eine Umbenennung nicht das falsche Feld trifft, trägt jeder Wert jetzt neben entryType ein neues field: GatherField; MOOD und EXCRETA haben keine Textfelder (gatherFields = leer). Drei Helfer in GatherEngine.kt bilden die Brücke zwischen Modell und Screen: gatherFields (Textfelder eines Typs in Anzeigereihenfolge), gatheredTextOf(field) (aktueller Text) und withGatheredText(field, value) (Kopie mit gesetztem Feld). Sonderfälle: ein Getränk liefert nur drinkName, eine Mahlzeit/Snack nur foodText, und der Medikamenten-Name wird übersprungen, wenn er nur den Wirkstoff spiegelt (seit v57 wird er beim Speichern so gesetzt) – sonst stünde jeder Wirkstoff zweimal in der Liste. Vorlagen sind ausgeschlossen: sie sind keine geloggten Eintraege und wuerden nur die Zaehler aufblaehen. ProposalEngine.scanRecurringPatterns hat dieselbe Sicht und traegt field in RecurringPattern mit. renameGatheredText/mergeGatheredTexts im JournalViewModel nehmen dadurch (type, field, …) und schreiben ueber withGatheredText nur dieses Feld (withRenamedGatheredText zieht den gespiegelten Medikamenten-Namen mit, wenn der Wirkstoff umbenannt wird; ein Legacy-Name, der vom Wirkstoff abweicht, bleibt stehen). GatheredScreen rendert eine Sektion je Eintragstyp (Ueberschrift ueber entryTypeLabel, Farbe ueber entryTypeColor, Reihenfolge EntryType-Ordinal, leere Typen erscheinen gar nicht) statt zwei fest verdrahteter Trigger-/ Skill-Listen; bei Typen mit mehreren Textfeldern (Highlights, Medikament) steht das Feld-Label (gatheredFieldLabel) in der Meta-Zeile. Das Merge-Zielmenue listet nur Werte desselben Feldes – ein Wirkstoff laesst sich nicht in eine Dosis zusammenfuehren – und die Menu-Oeffnung vergleicht mergeSource per Identitaet statt per Text (sonst wuerde ein Text, der in mehreren Feldern vorkommt, zwei Menues gleichzeitig oeffnen). Der Trigger-/Skill-Editor filtert seine Vorschlage zusaetzlich auf field == TEXT, damit nicht Wirkstoffe oder Begruendungen als Ausloeser-Vorschlag auftauchen. Settings-/Screen-/Tutorial-Texte, DE+EN, angepasst (gathered_section_triggers/_skills entfallen zugunsten der Typ-Labels, neu gathered_field_*). SRS 1.7.0.

(2) Einstellungs-Sektion "Datenschutz" -> "Verbergen". Der Weichzeichner (Aus / 7 / 14 / 30 Tage) ist unveraendert, nur die Ueberschrift war falsch – sie beschrieb eine Absicht (Datenschutz), nicht das, was die Einstellung tut. settings_section_privacy heisst jetzt settings_section_hide ("Verbergen" / "Hide"). PrivacySettings (KDoc, Repo-Prefs privacyBlurDays, Blur im Karussell) bleibt unangetraendert. SRS 1.7.0.

(3) Tutorial: "Stimmung & Auswertung" -> Bericht, Medikamenten-Seite korrigiert. Die Tutorial-Seite tutorial_eval_* ("Stimmung & Auswertung") war doppelt falsch: Sie versprach ein einstellbares Auswertungsfenster (7–365 Tage) in den Einstellungen – das gibt es nicht mehr, seit v93 ist die Auswertungs-Karte entfernt und evaluationWindowDays() fest 30 Tage. Sie heisst jetzt "Bericht für den Arzt" / "Doctor's report" (tutorial_report_*, Icon Icons.Filled.Description statt Insights) und beschreibt den Klartext-Bericht: chronologisch, ohne Vorlagen, vor dem Erstellen waehlbare Eintragstypen, erreichbar ueber Einstellungen → Sicherung → Bericht (export_title DE "Sicherung" / EN "Backup", ReportCard). Die Statistik-Seite bleibt unberuehrt – der Statistik-Screen deckt weiterhin nur Trigger/Skills ab, wie tutorial_stats_body sagt. Die Medikamenten-Seite behauptete zudem, "Medikamenten-Erinnerungen loggen die Einnahme direkt ins Journal". Das ist seit v125 nicht mehr die Besonderheit von Medikamenten, sondern eine Einstellung je Vorlage (direct:add, edit_direct_add_on, seit v125 fuer alle Eintragstypen): tutorial_medicine_body beschreibt jetzt Vorlage + die Wahl zwischen direkt eintragen und Editor mit vorausgefuelltem Eintrag. Die Medikamenten-Erinnerungen aus den Einstellungen (MedicineReminderSettings, drainPendingMedicine → writeMedicineDraftNow) loggen weiterhin direkt – nur ist das nicht mehr die Aussage der Tutorial-Seite.

(4) Sprache folgt dem System, kein Schalter mehr. Die Einstellungen hatten zwei Sprach-Buttons (Deutsch/Englisch), die ueber LocalePrefs eine Praeferenz in den SharedPreferences speicherten und die Activity neu erzeugten. Der Schalter ist ersatzlos entfallen: die App zeigt Deutsch auf einem deutschen System und ueberall sonst Englisch. Dazu die Speicherrichtung gedreht – res/values/strings.xml (bisher Deutsch) ist jetzt Englisch und der bisherige values-en-Ordner traegt Deutsch als res/values-de/strings.xml. Das ist die Konvention, die der Launcher schon hatte (EN default, DE qualifiziert) und die Android von selbst richtig aufloest; die values-en-Datei loest nur noch bei englischer Systemsprache, nicht mehr bei jedem Nicht-Deutsch. LocalePrefs.kt ist geloescht, ebenso die beiden attachBaseContext-Ueberladungen, die die Activity-Kontexte in die gespeicherte Sprache umhiengen. SecretaryJournalApp.localizedContext() liefert damit einfach baseContext und bleibt nur als Zugriffspunkt fuer VM-Texte und Receiver-Benachrichtigungen bestehen. AndroidManifest listet locale nicht unter configChanges, ein Systemsprachwechsel erzeugt die Activity also ohnehin neu – deshalb reicht der Wegfall des Schalters voll aus. settings_section_language und settings_language_* (4 Strings) sind weg, beide Sprachdateien haben denselben Schluesselbestand (378 Namen). SRS 1.7.0, FR-J-62/121.

(5) Gemeinsamer Einstellungs-Screen: Versionszeile statt Namensraum. Der collectionNamespace-Parameter und die Karte Namensraum sind aus SecretarySettingsScreen entfernt; Journal, Launcher, Links, Notizen, Secrets und Tasks rufen die Funktion jetzt ohne das Argument auf (die Konstanten LINKS_NAMESPACE, NotesRepository.NAMESPACE, TasksRepository.NAMESPACE, LauncherRepository.NAMESPACE und "/secrets/" sind an den Aufrufstellen danach unbenutzt und die Importe mit verschwunden; die Konstanten selbst bleiben, sie sind der CalDAV-Basispfad). Die Karte zeigte eine Konstante, die der Nutzer ohnehin in der Collection-Liste sieht – Information ohne Handlung, also weg. Die Karte Sammlungspräfix (Kalender, Kontakte) bleibt, dort ist der Wert konfigurierbar. Neu ist die letzte Zeile des Screens: die Version der jeweils laufenden App, gelesen aus der PackageInfo des eigenen Pakets (versionName, ersatzweise versionCode fuer API 26/27, wo es longVersionCode noch nicht gibt, PackageInfoFlags ab API 33) – jedes Modul zeigt so seine eigene Nummer, ohne sie durchzureichen. Das betrifft alle acht Apps, weil sie den Screen gemeinsam nutzen. Ein settings_version-String liegt in common DE+EN, die Karte Sammlungspräfix (Kalender, Kontakte) bleibt unangetastet. SRS journal 1.7.0 FR-J-64, SRS common 1.3.0.

versionCode 139 -> 140. CONTEXT.md updated.

Status 2026-09-30 (139)

Secretary Journal 139 (versionCode 139): keine Code-Aenderung - der Quelltext ist derselbe wie bei 138. Veraendert wurde in diesem Zug nur der Launcher (Korrektur am Konfigurations-Sync, dort 460). Die Nummer geht trotzdem hoch, weil ein Release alle acht Clients und beide Serverpakete zusammen ausliefert: das Buildsystem ueberspringt einen Lauf, dessen Zieldateinamen alle bereits im Archiv liegen, und ein gleichnamiges Paket mit gleichem Inhalt waere auf dem Geraet nicht von 138 zu unterscheiden - bei einer APK zusaetzlich ein versionCode, den ein Geraet nicht neu installiert. Server und check-links gehen mit auf 0.24.0. versionCode 138 -> 139.

Status 2026-09-29 (138)

Secretary Journal 138 (versionCode 138): Abschluss des Release-Zugs, der Signiermaterial aus einer Umgebungsvariable in eine Datei verlagert hat (siehe 137). Der Sprung ist der von 4d6b02eee5 für alle acht Module gemeinsam gesetzte: BuildManager vergleicht Dateinamen, nicht Inhalte, also liefert derselbe Code ohne neue versionCode exakt denselben Namen und der Build wird als „bereits im Repo“ abgewiesen. Am Journal änderte sich in diesem Schritt kein Funktionscode. versionCode 137 -> 138.

Status 2026-09-29 (137)

Secretary Journal 137 (versionCode 137): alle acht Clients signieren ihre Release-APKs, nicht nur der Launcher. Vorher konnte nur der Launcher überhaupt ein signiertes APK liefern, die sieben anderen Module hatten gar kein signingConfig und bauten deshalb *-unsigned.apk. Zwei Nacharbeiten blieben in derselben Version: der Default-Pfad für das Keystore war um eine Ebene zu kurz, und die Zugangsdaten wurden aus dem Prozess-Environment in eine Datei verlagert, damit ein Release nicht von einer in keinem --help genannten Umgebungsvariable abhängt. versionCode 136 -> 137.

Status 2026-09-29 (136)

Secretary Journal 136 (versionCode 136): Signiermaterial in ein eigenes Fossil-Repository signing-certs ausgelagert (vorher lag es im Secretary-Repository selbst, zwischen Anwendungscode und Release-Skripten). Am Journal änderte das keine Zeile Funktionscode; die Version trägt die neue Signierkonfiguration und macht damit überhaupt erst ein signiertes Release-APK möglich. versionCode 135 -> 136.

Status 2026-09-29 (135)

Secretary Journal 135 (versionCode 135): Konto, gemeinsamer Einstellungs-Screen und Konfigurations-Sync für den Launcher. Der Commit hielt die versionCode aller acht Module gleichzeitig fest, damit der Release-Zug überhaupt laufen konnte. Am Journal selbst änderte sich dabei keine Zeile; die Funktionsänderung betraf ausschließlich den Launcher. Die Nummer 134 wurde nie vergeben — dieser Commit sprang von 133 auf 135. versionCode 133 -> 135.

Status 2026-09-26 (133)

Secretary Journal 133 (versionCode 133): Typewriter-Launcher-Icon [:-)] (vorher [☺]). Die Glyphe wird jetzt wie bei allen anderen Apps mit Special Elite gerendert — : , - und ) deckt der Font ab, nur ☺ (U+263A) fehlte, weshalb bisher das gebündelte Liberation Mono nötig war. Da das : in der Glyphe den Trenner der APPS-Tabelle kollidiert hat, ist das Schema auf |-getrennte Felder umgestellt (Kommentar in tools/generate-icons.sh entsprechend angepasst, SMILEY_FONT heißt jetzt FALLBACK_FONT; der font-override-Mechanismus bleibt für Glyphen erhalten, die Special Elite nicht deckt). Accent #5A7A3E und Adaptive-Icon-XML unverändert, die 5 Foreground-PNGs neu erzeugt. versionCode 132 -> 133. CONTEXT.md updated.

Status 2026-09-24 (132)

Secretary Journal 132 (versionCode 132): Typewriter-Launcher-Icon [☺]. Das Journal bekommt das gemeinsame Secretary-Icon-Schema der übrigen Apps (tools/generate-icons.sh): eine weiße Glyphe auf dem App-Akkzent #5A7A3E. Da Special Elite das Smiley-Zeichen ☺ (U+263A) nicht abdeckt, rendert der Generator das [☺] im gebündelten Liberation Mono (SIL OFL 1.1, tools/liberation-mono/); die APPS-Tabelle unterstützt dafür ein optionales fünftes Feld font-override. Die 5 Foreground-PNGs liegen wie bei den anderen Apps in mipmap-{mdpi..xxxhdpi}/ic_launcher_foreground.png, der Adaptive-Icon-XML referenziert @mipmap/ic_launcher_foreground, die alte Vektor-Foreground- Datei (drawable/ic_launcher_foreground.xml) ist entfernt, der Hintergrund bleibt #5A7A3E. versionCode 131 -> 132. CONTEXT.md updated.

Status 2026-09-23 (131)

Secretary Journal 131 (versionCode 131): Fixes: „Direkt eintragen"- Vorlagen öffnen trotzdem den Editor; bei mehreren aktiven Erinnerungen verwechseln die Sofort-Aktionen Einträge.

(1) Stale Vorlagen-Snapshot (Editor öffnet trotz direct:add). PendingTemplateQueue.enqueuePending überschrieb einen vorhandenen Snapshot nicht (Dedup-Skip) — ein Snapshot wurde beim ersten arm() eingefroren und nie aktualisiert. Ein späterer Vorlagen-Edit (z. B. directAdd einschalten) kam also nie im Snapshot an, und performAccept klonte den alten Snapshot: der Editor öffnete trotz „Beim Annehmen direkt eintragen". Neu ersetzt enqueuePending einen vorhandenen Eintrag (Upsert) — jeder arm() über rearmAll (Speichern/Start/onResume) frischt den Snapshot mit dem aktuellen Vorlagen-Stand (inkl. directAdd, Text, …) auf; ebenso ersetzt enqueuePendingEdit ältere Entwürfe derselben Vorlage (jüngster Accept gewinnt).

(2) Sofort-Aktionen verwechseln Einträge bei mehreren aktiven Erinnerungen. Zwei Ursachen behoben: (a) PendingIntent-Kollisionen: alle Vorlagen-/Medikament-PendingIntents trugen ihre Identität nur in Extras + Request-Code (BASE + (hash mod 100000) + Slot-Offset, Feuer-Slots ±63 → Kollisionsfenster) mit FLAG_UPDATE_CURRENT; eine Kollision überschrieb die Extras eines bereits geposteten Benachrichtigungs-Actions, die Accept/Reject-Feuerung lief dann für die falsche Vorlage. Neu trägt jeder Intent eine eindeutige data-URI (secretary-journal://template/ <uid>/<code> bzw. …/medicine/<id>/<index>[/confirm]), sodass filterEquals die Tokens unabhängig vom Request-Code unterscheidet — TemplateAlarmScheduler, TemplateReceiver (Accept/Reject) und die Medikamenten-Alarme/-Actions. (b) Direct-Add-Wedge: die Direkt-Protokollierung lief durch editingEntry = draft; saveEntry() (asynchron) — bis die Speicherung fertig war, war editingEntry belegt, weitere Accepts wurden geparkt und später FIFO (falsche Reihenfolge/stale) geöffnet; ein fehlgeschlagener Save (kein activeCollection) ließ editingEntry dauerhaft belegt, wodurch alle weiteren Accepts stehen blieben und nach Entsperren/Editor-Schließen fremde Entwürfe aufsprangen. Neu loggt der Direct-Add-Pfad ohne editingEntry (writeTemplateDraftNow, analog writeMedicineDraftNow; bei Fehlschlag wird der Entwurf wieder eingereiht und nach Collections-/Entries-Load erneut versucht via drainDirectAddDrafts), handleTemplateAccept prüft per peekPendingEdit auf Direct-Add, und die FIFO-Drains (drainPendingTemplateEdits/drainIdlePendingTemplateEdit) drainen Direct-Add-Entwürfe direkt und öffnen nur den ersten Editor-Entwurf; runTemplateNow („Jetzt eintragen") nutzt denselben Direct-Add-Pfad. Die Sofort-Aktionen sind damit unabhängig von einem offenen Editor und von kollidierenden Request-Codes. versionCode 130 -> 131. CONTEXT.md updated.

Status 2026-09-22 (130)

Secretary Journal 130 (versionCode 130): Neuer Eintragstyp „Gewohnheit" (Habit). EntryType.HABIT("habit") (Reihenfolge der entries am Ende, FAB-/Checklisten-Block automatisch) mit einem Freitextfeld (text, HabitEntryBody im Editor: edit_habit_question; verschlüsselbar wie TRIGGER/SKILL als einzelner sj1:-Blob, JSON-Schlüssel text bleibt, kein Schema-Bump) und ohne Tendenz (Statistik/Gathered unberührt). Persistiert als VJOURNAL SUMMARY=habit, DESCRIPTION = Text, CATEGORIES=[habit, is:template, rrule:*, rand:N, direct:add, at:*] — d. h. vollständig Vorlagen-tauglich (fest/zufällig, Direct-Add, Accept/Reject, „Jetzt eintragen"), der Type-agnostische Scheduler/Receiver braucht keine Änderung. Neu in JournalViewModel: openHabitEntryForDate / createNewHabitEntry, HABIT in den Entschlüsselungs-Pfaden und der Import-Mergung. Icon Icons.Filled.Checklist, Farbe HabitColor (Indigo 0xFF3F51B5), Labels type_habit / edit_subtype_habit (GEWOHNHEIT/HABIT) DE+EN. Editor, FAB, Kalender-FAB/-Teilen-Text, JournalTypeUi (Icon/Label/Farbe/Titel) und Klartext-Bericht erweitert; der Report-Dialog (ReportCard) listet den Typ automatisch über EntryType.entries. versionCode 129 -> 130. CONTEXT.md updated.

Status 2026-09-19 (129)

Secretary Journal 129 (versionCode 129): Eigener Namespace-Root /journal/ statt /calendars/journal-* (Namespace-Migration, server 0.16.0). Das Journal legt seine Sammlungen jetzt unpräfixiert unter dem top-level Root /journal/ an (kanonische Sammlung: main unter /journal/main/; zuvor /calendars/journal-main/). JournalRepository nutzt baseCollectionPath = "/journal/" (neue CaldavClient.collectionRoot), der NotesCodec ist NotesCodec(collectionBasePath = "/journal/") (unpräfixiert), die Sync-Sektion zeigt „Namensraum" statt „Sammlungspräfix". Der Offline-Cache wird beim ersten Lesen automatisch über die neue GOfflineStore.legacyPrefix = "journal-"-Eigenschaft migriert (/calendars/journal-* → /journal/…, idempotent; die lokale Pseudo-Collection /local/ bleibt unangetastet). runServerSync filtert zusätzlich /journal/ (Legacy-/calendars/, /addressbooks/ bleiben im Filter), der leere Server legt main an. Deployment-Reihenfolge: erst Server auf 0.16.0 updaten + migrate-namespaces.sh laufen lassen, dann die App ausrollen. versionCode 128 -> 129. CONTEXT.md updated.

Status 2026-09-18 (128)

Secretary Journal 128 (versionCode 128): Fix: „Eintragen"-Benachrichtigung öffnet den falschen (oder keinen) Eintrags-Editor.

Root cause. Beim Kaltstart über die Accept-Benachrichtigung lief JournalViewModel.init sein FIFO-drainPendingTemplateEdits() vor dem per-UID-Accept (MainActivity.handleTemplateAccept): Es hob den ältesten Entwurf aus der Pending-Edit-Queue ab (ein liegengebliebener Entwurf eines früheren, nie geöffneten Accepts — z. B. wenn die App beim Annehmen gesperrt war oder der Editor offen), öffnete dessen Editor (falscher Typ) und der eigentliche Accept brach wegen editingEntry != null ab — bzw. gar kein Dialog, wenn der stale Entwurf direct:add war und direkt speicherte. Zusätzlich konnte editingEntry nach dem Verlassen des Editors über System-Zurück (kein onClose) non-null bleiben, sodass spätere Accepts in der Queue parkten und als falscher Typ aufpoppten. Korrektur: (1) Accept ist jetzt strikt uid-basiert — drainPendingTemplateEdits() wird nicht mehr bei jedem Start gerufen (nur noch nach Entsperren), der kalte Start verarbeitet den angenommenen templateUid über handleTemplateAccept → drainPendingEdit(uid) und öffnet immer den Editor des angenommenen Typs. (2) System-Zurück == Editor-schließen: Der EDIT-Route im NavGraph hat ein BackHandler, das dieselbe Close-Kette ausführt (closeEditor() + popBackStack() + drainIdlePendingTemplateEdit()), sodass kein Entwurf mehr verwaist. (3) Stale-Expiry: PendingTemplateQueue.loadEdits() verwirft Entwürfe älter als 24 h (Schlüssel occurredAt = Accept-Zeit) und persistiert die Bereinigung — der betroffene, monopol laufende Entwurf wird so von Geräten abgeräumt und kann nie wieder als falscher Typ erscheinen.

Tages-Highlight (FREQ=DAILY, TEXT) auch im Accept-Pfad find-or-open. Die v121-FREQ=DAILY-Kopie im Vitual-/Accept-Pfad war tot, weil TemplateReceiver.performAccept den Entwurf mit isTemplate=false und rrule="" klonte. Neu behält ein Nicht-Direct-Add TEXT+FREQ=DAILY-Entwurf seine isTemplate/rrule-Identität (übersteht den JSON-Round-Trip der Pending-Edit-Queue), und openPendingTemplateDraft routet ihn wieder auf openTextEntryForDate(LocalDate.now()) — der bereits vorhandene Tages-TEXT- Eintrag (Highlights) wird geöffnet bzw. neu angelegt statt eine Duplikat- Kopie zu erzeugen. In allen Nicht-Highlight-Pfaden (Direct-Add und Fall-through) werden isTemplate/rrule vor dem Editor strikt entfernt — ein Entwurf kann nie als Vorlage gespeichert werden oder die Vorlagen-Maske zeigen; Verhalten konsistent mit runTemplateNow. versionCode 127 -> 128. CONTEXT.md updated.

Status 2026-09-18 (127)

Secretary Journal 127 (versionCode 127): Datenschutz-Weichzeichner (Privacy Blur) + Tendenz-basierte Stimmungs-Anpassung (SRS §4.14, FR-J-130–134).

(1) Privacy Blur. Neue Einstellungs-Sektion „Datenschutz" (PrivacySettings, in SettingsScreen zwischen Ruhezeit und Stimmung): wählbar Aus / 7 / 14 / 30 Tage (Default Aus, JournalRepository.privacyBlurDays()/savePrivacyBlurDays, Prefs-Key privacy_blur_days). Ist sie aktiv, rendert JournalCarouselScreen alle Tag-Zeilen der Eintragsliste unabhängig vom Alter hinter einem Weichzeichner (Modifier.blur(10.dp), blurred-Parameter an DayListRow), nur der Stimmungs-Smiley (Hero) oben bleibt klar sichtbar; die Vorlagen-Liste und die übrigen Kopfbereiche (Sync, Tendenz-Zählzeile) bleiben ungeblurrt. Tippen bleibt funktionsfähig (öffnet weiter den Editor).

(2) Tendenz-basierte Stimmungs-Anpassung. Neue Einstellungs-Sektion „Stimmung" (TendencyMoodSettings): ein Schalter „Stimmung automatisch anpassen" (Default Aus, Prefs-Key tendency_mood_enabled) plus eine Schwelle X = 1/2/3 (Default 2, tendencyMoodThreshold()/ saveTendencyMoodThreshold, Prefs-Key tendency_mood_threshold). Der ViewModel liefert neu displayedDominantMood: Ist der Schalter an und liegt mindestens ein Stimmungs-Eintrag vor, zählt er die Tendenzen aller Nicht-Vorlagen-Einträge nach dem zeitlich letzten Stimmungs-Eintrag (entryTimeMs), net = up − down; bei net ≥ X wird die Stimmung eine Stufe höher, bei net ≤ −X eine Stufe tiefer angezeigt (Mood.numericValue ± 1, über die fünf Stufen begrenzt), sonst unverändert. Der Karussell-Hero nutzt vm.displayedDominantMood statt vm.latestMood. Reine Anzeige-Kuration: gespeicherte Einträge, Statistik, gesammelte Werte und Export bleiben unberührt (FR-J-134). DE/EN-Strings settings_section_privacy/settings_privacy_blur_* und settings_section_mood/settings_tendency_mood_* ergänzt. SRS 1.5.0. versionCode 126 -> 127. CONTEXT.md updated.

Status 2026-09-18 (126)

Secretary Journal 126 (versionCode 126): Fix: Einträge nach App-Start verschwunden (bis zum Sync) + stale Vorlagen-Editor-Dialog.

(1) Cache-Korruption durch die lokale Pseudo-Collection. Seit der Single-Flavor-Zusammenführung lief ensureLocalCollection() unbedingt bei jedem Start: Fehlte im Store eine Collection mit der exakten Id journal, überschrieb es die gesamte Collection-Liste des Stores mit nur der lokalen Pseudo-Collection (id "journal", href "/local/"). Echte Server-Collections heißen aber nie journal (das Journal legt sie als journal-journal über NotesCodec("journal-") an), die Guard schlug also immer fehl → der Store war nach jedem Start korrupt: activeCollection() lieferte die leere Pseudo-Collection, der Start-Cache blieb leer („alle Einträge weg") und saveEntry PUT auf "/local/<uid>.ics" → Server-400 DavException („Speichern schlägt fehl"), bis ein erfolgreicher Sync die Collections neu lud. Gestalt der Korrektur: (1) ensureLocalCollection() wirkt nur noch im lokalen Modus und merged die Pseudo-Collection dazu statt die Liste zu ersetzen (Remote-Modus: die Store-Collection-Liste ist der Server-Cache und bleibt unangetastet). (2) activeCollection() filtert im Remote-Modus die Pseudo-Collection heraus (id journal + href /local/) — Selektion und Journal-supportsJournal-Fallback laufen nur gegen echte Server-Collections; im Lokal-Modus bevorzugt die Funktion den Pseudo-Eintrag nur, wenn er tatsächlich Einträge trägt (sonst fällt sie auf eine Collection mit Einträgen zurück, z. B. nach Logout). (3) Self-Healing für bereits korrupte Caches: recoveredRemoteCollection() leitet die echte Server-Collection aus den gecachten Item-hrefs (/calendars/<id>/…) und den Pending-PutItem-hrefs ab (bevorzugt last_collection), healAwareCollections() blendet sie effektiv ein und healRemoteCollectionCache() persistiert sie (gstore.setCollections, saveLastCollectionId); gerufen im init-Koroutinen-Zweig (Remote), in loadStartupCache und in loadFromCache (Offline-Pfad). Damit zeigt auch ein bereits beschädigter Cache beim nächsten Start sofort wieder seine Einträge — ohne auf einen Sync warten zu müssen. Der v120-Filter (runServerSync sendet nur /calendars/- bzw. /addressbooks/-hrefs) und der bestehende Offline-Handoff bleiben unverändert.

(2) Staler Vorlagen-Editor. Wurde eine Vorlage per Benachrichtigung angenommen, während der Editor bereits offen war (editingEntry != null), blieb der Entwurf in der Pending-Edit-Queue liegen und wurde in derselben Sitzung nie mehr geöffnet — beim nächsten Start popte drainPendingTemplateEdits() den uralten Entwurf ungefragt als „stale Edit-Dialog" auf. Zusätzlich wurde der One-Shot-Zähler templateEditRequest nie zurückgesetzt: der LaunchedEffect(templateEditRequest) im NavGraph navigierte dadurch bei jeder frischen Recomposition (z. B. nach dem Entsperren) erneut auf Routes.EDIT, auch ohne neuen Vorlagen-Auftrag. Korrektur: (1) Der EDIT-onClose im NavGraph ruft nach closeEditor() + popBackStack() jetzt vm.drainIdlePendingTemplateEdit() auf — ein währenddessen angenommener Entwurf wird unmittelbar im Editor geöffnet (Chain), ein zurückgestellter Entwurf kann nicht mehr über Nacht „verklumpt" erscheinen. (2) consumeTemplateEditRequest() setzt den Zähler direkt nach dem Navigieren auf 0 — die Editor-Auto-Öffnung ist wieder einmalig pro Entwurf; Unlock-/Start-Pfade (drainPendingTemplateEdits) bleiben. versionCode 125 -> 126. CONTEXT.md updated.

Status 2026-09-18 (125)

Secretary Journal 125 (versionCode 125): Vorlagen-Fixes: Direct-Add funktioniert für alle Typen + ehrliche Zufalls-Zeiten per Teil-Methode (FR-J-71/84/85).

(1) Direct-Add-Fix: Bei Vorlagen mit „Direkt eintragen" (direct:add) wurde beim Annehmen nie ein Eintrag angelegt — performAccept klont die Vorlage in einen Entwurf mit isTemplate=false, daher war der direkte Protokoll-Pfad unerreichbar: openPendingTemplateDraft verlangte decrypted.isTemplate (immer false) und zusätzlich entryType == TEXT. Neu: if (decrypted.directAdd) reicht, und auch runTemplateNow („Jetzt eintragen") verlangt statt isTemplate && entryType == TEXT && directAdd nur noch isTemplate && directAdd. Damit loggt eine Direct-Add-Vorlage beim Annehmen (bzw. „Jetzt eintragen") für alle Eintragstypen direkt ohne Editor (z. B. Medikamente). Die Kommentare am Accept-Pfad sind bereinigt (Vorlagen-Entwurf trägt nach dem Klon stets isTemplate=false).

(2) Zufalls-Zeiten ehrlich (Teil-Methode): Die alte randomBlock zog für den ersten kommenden Vorkommens-Tag count Slots in das gegen „jetzt" beschnittene Fenster — jedes Accept/Reject (Re-Arm) zog dadurch count frische Slots im Restfenster von heute, verdoppelte Termine und zählte nie ehrlich. Neu (SRS FR-J-84/85): Die Tages-Feuerzeit (ganzer Tag minus Ruhezeit, zusammenhängende Minuten-Spannen aus dayFiringChunks(), Total in totalMinutes) wird in count gleiche aufeinanderfolgende Teile geteilt; jedes Teil liefert genau einen deterministischen Zufalls-Slot (DeviceTimePolicy.pickRandomMillis(uid, day, partStart*60_000, partEnd*60_000, salt = k*1013+k)), bereit im Teil bereits abgelaufene Teile werden übersprungen. Dadurch bleibt die Anzahl pro Tag bei count (geteilt nach dedup), Re-Arm reproduziert exakt dieselben absoluten Zeiten und das Fenster verschiebt sich nicht: überfällige Teile fallen weg, restliche Teile bleiben auf ihren bewaffneten Zeiten; sind alle Teile des heutigen Tages vorbei, wandert der Rest auf die folgenden Vorkommens-Tage (Guard < 60), bis count zukünftige Slots stehen. randomBlock ist signature-bereinigt ((template, base) ohne context, beide Aufrufer arm/nextRandomFire angepasst) und die KDoc am Scheduler und randomBlock beschreiben die Teil-Methode. SRS 1.4.0. versionCode 124 -> 125. CONTEXT.md updated.

Status 2026-09-17 (124)

Secretary Journal 124 (versionCode 124): Passwort-only-Verschlüsselung (FR-J-90/95/96/97). Das bisherige Master-Key-Schema (zufälliger AES-256-Schlüssel, per PBKDF2-Passwort gewrappt) ist ersetzt: der PBKDF2-HmacSHA256-abgeleitete Schlüssel (210k Iterationen, salzfrei) dient direkt als AES-256-GCM-Schlüssel — es gibt keinen separaten Master-Key mehr. Damit genügt das Passwort allein, um das Journal nach Neuinstallation, Reconnect oder Import wieder zu entschlüsseln. JournalCipher: enable()/disable()/changePassword() arbeiten auf dem abgeleiteten Schlüssel; die Passwortprüfung läuft über ein Verifier-Token (KEY_VERIFIER, AES-GCM über den festen Text secretary-journal-verifier); Alt-Installationen bleiben über den Legacy-Wrap (KEY_PW_WRAP, unwrapLegacyMaster) entsperrbar, bis ihre Einträge neu kodiert sind. Die Biometrie wrappt jetzt den Session-Schlüssel. Setzen/Entfernen/Ändern verschlüsselt bzw. entschlüsselt alle Einträge (JournalViewModel.runMigration + pushAllEntries(onProgress), CryptoMigration-State) und wird im UI von einem Warn-Dialog (CryptoWarningDialog, Wirkung auf alle N Einträge) und einem nicht-abbrechbaren Fortschritts-Overlay (CryptoMigrationDialog, „Eintrag X von Y wird verschlüsselt/entschlüsselt") begleitet. Das Tutorial hat die Verschlüsselungs-Einrichtung als letzten Schritt (TutorialTry.ENCRYPT -> Einstellungen). DE/EN-Strings ergänzt. SRS 1.3.0. versionCode 123 -> 124. CONTEXT.md updated.

Status 2026-09-17 (123)

Secretary Journal 123 (versionCode 123): Vorlagen-Maske visuell unterscheidbar (FR-J-82/83). Der Editor zeigt beim Erstellen/Bearbeiten einer Vorlage jetzt eine eigene, klar erkennbare Maske statt einer Eintrags-Maske mit Zusatzfeldern: (1) Header-Badge — statt der Datums-Unterzeile mit Typ + Uhrzeit steht „VORLAGE · <TYP>" (edit_template_subtitle, DE/EN), ergänzt die SRS FR-J-82; (2) eigener Vorlagen-Abschnitt — der Template-only-Block (Zeitpunkt/Wiederholung/ Zufallsplan) ist unter dem Section-Titel „VORLAGE" gruppiert, die Wiederholung heißt „Wiederholung der Vorlage" (edit_template_recurrence), ein Hinweistext erklärt, dass die Vorlage wiederholt erinnert und erst beim Annehmen ein Eintrag daraus entsteht (edit_template_fires_hint); (3) Vorlagen-Wortlaut — Speichern-Button „Vorlage speichern" (edit_save_template) und Löschen-Dialog „Vorlage löschen"/ edit_delete_template_{title,text} statt Eintrag-Wording. Normale Einträge zeigen die bisherige Eintrags-Maske unverändert (kein Vorlagen-Badge, kein Zufallsplan/Wiederholung). versionCode 122 -> 123. CONTEXT.md updated.

Status 2026-09-17 (122)

Secretary Journal 122 (versionCode 122): Ruhezeit-Korrektur: v93-Umbenennung jetzt durchgängig (Buttons zeigen 22:00–07:00 statt 07:00–22:00), Scheduler feuert außerhalb der Ruhezeit. Seit v93 ist die Einstellung der „Ruhezeit" (Quiet time) als Zeitraum ohne Erinnerungen definiert, der Code war aber nie gefolgt – JournalRepository.randomWindow() fiel weiter auf das alte Aktivfenster TimeRange.DEFAULT (07:00–22:00) zurück (die Buttons zeigten „Von 07:00 – Bis 22:00", der Info-Text darunter behauptete „Standard: 22:00–07:00") und die Validierung start <= end lehnte den Mitternacht-überspannenden Ruhezeit-Standard 22:00–07:00 beim Rücklesen ab. Neu: (1) randomWindow() gibt als Default die Ruhezeit 22:00–07:00 (quietDefault()) zurück, akzeptiert Wrap-Around-Bereiche (start > end, gleiche Start-/Endzeit = ganzer Tag ruhig) und migriert den v93-Legacy- Default 07:00–22:00 (unverändert gespeicherter alter Aktivzeitraum) auf den neuen Ruhezeit-Default – der Einstellungs-Screen zeigt damit konsistent „Von 22:00 – Bis 07:00". (2) TemplateAlarmScheduler behandelt das Fenster als Ruhezeit und feuert in deren Komplement: firingTimeRanges() bildet aus dem (ggf. über Mitternacht verlaufenden) Ruhefenster ein bis zwei nicht-wrappende Tagesfenster ab (z. B. Ruhezeit 22:00–07:00 → Feuerfenster 07:00–22:00; Ruhezeit 07:00–22:00 → die zwei Nachtsegmente 22:00–23:59 und 00:00–07:00), clampQuiet() wählt das erste mit DeviceTimePolicy.clampWindow gültige Fenster; randomBlock (Arm) und deferRandom (DND-Deferral) nutzen denselben Pfad. Damit bleiben die tatsächlichen Alarmzeiten auf frischen Installationen und nach der Legacy-Migration identisch (07:00–22:00), während ein gesetztes Ruhefenster jetzt wirklich bedeutet, dass dort keine Zufalls-Erinnerungen feuern. RandomWindowSettings-KDoc und Scheduler-KDoc aktualisiert. versionCode 121 -> 122. CONTEXT.md updated.

Dazu liefert dieser Build die abgeschlossene, zuvor abgebrochene secretary-common-android-Änderung mit: der gemeinsame RecurrenceDialog verliert das Freitext-RRULE-Feld („Benutzerdefinierte Regel", Kategorie showCustom/customRrule/customValid); der Aufbau ist rein Form-basiert (formRrule), eine bestehende nicht-parsebare RRULE wird unverändert übernommen (effective = currentRrule, wenn spec == null). Das unterbrochene Halbedit (Syntaxfehler, TimerText = remember) ist komplettiert, .bak-Datei entfernt, common-Unit-Tests grün.

Status 2026-09-16 (121)

Secretary Journal 121 (versionCode 121): Vorlagen-Erweiterung: Tages-Highlight + Direct-Add. Neue Themen aus den Nutzer-Antworten:

1) Tages-Highlight-Vorlage (FREQ=DAILY, TEXT). „Jetzt" (FAB) bzw. „Eintragen" (Notification) öffnet den bereits vorhandenen Tages-TEXT- Eintrag statt eine weitere Kopie zu erzeugen (find-or-open über openTextEntryForDate(LocalDate.now()), in runTemplateNow und im Accept-Pfad openPendingTemplateDraft). Nur für TEXT-EINTRAEGE mit FREQ=DAILY in der RRULE.

2) directAdd-Schalter (nur im Vorlagen-Editor). Ein neuer Schalter „Beim Annehmen direkt eintragen (kein Editor)" ist nur in der Editor-Ansicht der Vorlage sichtbar (if (vm.editingIsTemplate), nicht bei normalen Einträgen in JournalEditScreen.kt). Ist er aktiv, wird ein überfälliger Vorlagen-Eintrag beim Annehmen direkt geloggt (kein Editor), z. B. Medikamente, die sich nicht ändern und nur geloggt werden. Gespeichert als Kategorie direct:add + JSON-Feld directAdd (JournalModels.kt Feld directAdd: Boolean = false, JournalTransfer put/optBoolean). versionCode 120 -> 121. CONTEXT.md updated.

Secretary Journal 120 (versionCode 120): Fix: „Sync fehlgeschlagen: Sync-Dienst 400" beim App-Start. runServerSync() reichte jedes Collection mit nicht-leerem href an den Server weiter – auch die lokale Pseudo-Collection (id "journal", href = "/local/", wird bei jedem Start von ensureLocalCollection in den Store/das collections-State gesetzt). Der secretary-server akzeptiert aber nur Pfade unter /calendars/ oder /addressbooks/; für /local/ antwortet POST /sync/start mit 400 „Collection muss unter /calendars oder /addressbooks liegen" und der ganze Sync-Meldungs-Zyklus schlug beim Start fehl („always starts with sync error 400"). Neu filtert runServerSync die Collections auf echte Server-Sammlungen (href.startsWith("/calendars/") bzw. /addressbooks/): die lokale /local/-Collection wird nie mehr übertragen, Server-Sync läuft sauber. versionCode 119 -> 120. CONTEXT.md updated.

Status 2026-09-16 (119)

Secretary Journal 119 (versionCode 119): Fix: Endlos-Loop im Sync (Spinner bleibt für die gesamte Sitzung auf „Synchronisiere…"). runServerSync() lief direkt nach dem Start bzw. Login, während loadCollectionsInternal die Collections noch asynchron lädt – collections war in diesem Moment leer. Mit leerer Collection-Liste blieb der while (done.any { !it })-Poll-Loop unausgeführt, syncStatus blieb auf RUNNING (0/0) stehen und der Guard if (syncStatus?.state == RUNNING) return blockierte jede spätere runServerSync()-Wiederholung für den Rest der Sitzung – der Sync hing endlos fest (Verhalten passte dazu, dass erst ein App-Neustart half: dann wurden die Collections wieder aus dem Store geladen). runServerSync bricht jetzt bei leerer Collection-/Job-Liste sauber ab (syncStatus = null, kein RUNNING, der Guard blockiert nichts mehr). Zusätzlich ist der Poll-Loop hart begrenzt (maxPolls = 200 ≈ 100 s bei 500 ms): bleibt ein Server-Job unerwartet dauerhaft RUNNING, wird der Status nach Ablauf auf FAILED („Sync timed out") gesetzt statt den Loop endlos zu pollieren – der Endlos-Zustand kann damit nicht mehr entstehen. versionCode 118 -> 119. CONTEXT.md updated.

Status 2026-09-16 (118)

Secretary Journal 118 (versionCode 118): Härtung der gemeinsamen Sync-Engine (secretary-common-android v0.30.0) – kein Journal-Code, nur Dependency-Bump + Rebuild. Die OfflineSyncEngine ist so gehärtet, dass der Rollout in Tasks/Calendar/Contacts/Notes/Links ohne Datenverlust möglich ist: (1) Pending-Delete-Filter – Ressourcen, deren DeleteItem noch in der Write-Behind-Queue liegt, werden aus dem gemergten Cache ausgeschlossen und nie re-hochgeladen (verhindert die Auferstehung lokal gelöschter Einträge in der UI bzw. ein Re-PUT auf dem Server, solange der DELETE nicht geflusht wurde; vorher fehlte das im Engine-Vertrag, das Journal braucht es nicht, alle anderen Apps schon). (2) prepare-null behält die Cache- Kopie statt sie zu verwerfen (ein nicht entschlüsselbarer/nicht uploadfähiger Eintrag bleibt im Cache und wird beim nächsten Sync erneut versucht – niemals Datenverlust). (3) Stale-Queue-Put-Cleanup – nach einem erfolgreichen Inline-Upload wird der zugehörige PutItem aus der Queue entfernt, sodass flushPending keinen veralteten (z. B. anders verschlüsselten) Body über die frisch hochgeladene Ressource legt. Neue Tests in common: OfflineSyncEngineTest jetzt 16 Tests (Server-Item + Cache-Item mit DeleteItem-Queue, prepare-null-Keep, Inline-Upload räumt Queue-Put); Gesamt-Suite 67 Tests grün. versionCode 118 == versionCode/intern 117 -> 118.

Status 2026-09-16 (117)

Secretary Journal 117 (versionCode 117): Single-Flavor-Journal an der gemeinsamen Sync-Engine aus secretary-common-android v0.29.0 (on-demand). Die Handoff-Logik (Fetch, Re-Homing device-only-Uids, Cache-Ersetzung, Offline-Erkennung) lebt nicht mehr im Journal, sondern in der neuen gemeinsamen OfflineSyncEngine (secretary-common-android/src/main/java/ org/beowulf/secretary/common/OfflineSyncEngine.kt): ItemRemote (listItemsRemote/saveItem/saveItemOffline), ItemsLoadResult (Synced/Offline) und CrudItemRemote (Produktions-Seam um CrudManager). Das Journal delegiert in loadEntriesInternal an OfflineSyncEngine(codec, gstore, CrudItemRemote(makeCrud())) und parametrisiert sie mit einem prepare-Lambda (JournalEntry.toNote(JournalEntry.fromNote(note, decryptEntryTexts()), encryptText()), runCatching → null überspringt den Upload, behält die Cache-Kopie) und onDavError → logErr. Damit nutzt das Journal dieselbe verlifizierte Engine wie Tasks/Calendar/Contacts statt einer eigenen Kopie. Wichtigster nebenläufiger Fix (aus der gemeinsamen Verallgemeinerung übernommen): DavException (extends IOException) wird vor dem IOException-Branch gefangen – ein Server-Reject hält den Eintrag im Cache und meldet ihn über onDavError, statt in die Offline-Queue zu wandern. Die Test-Suite ist komplett nach common verlagert und generalisiert: secretary-common-android/src/test/.../OfflineSyncEngineTest.kt (16 Tests, JUnit4 + runTest, getrieben über NotesCodec/Note und einen FakeRemote) deckt ab: lokaler Modus (Store als einzige Quelle, Persistenz, keine Pending-Queue bei reinen Store-Writes), erster Connect (Re-Homing+Upload device-only, Server-only/Shared-Uid-Merge ohne Re-Upload, leeres No-Op-Sync), prepare (Re-Encode für den Upload, null → Upload ausgelassen, Cache-Kopie behalten), Sicherheit (pending-gelöschte Ressourcen bleiben aus dem Cache/ werden nie neu hochgeladen, erfolgreicher Inline-Upload räumt den stale Queue-Put), Transport-Fehler beim Upload (IOException → saveItemOffline), Server-Reject (DavException → Cache + onDavError, nichts gequeued), Fetch-Fehler (IOException → Offline + Cache unangetastet, DavException propagiert) und Persistenz des gemergten Zustands. Gesamte common-Suite grün (67 Tests, davon 16 Engine). Die Journal-eigenen JournalSyncEngine.kt/JournalSyncEngineTest.kt (app/src/test) sind gelöscht, die Test-Abhängigkeiten (org.json, kotlinx-coroutines-test, isReturnDefaultValues) aus app/build.gradle.kts entfernt (dort liegen sie in common). versionCode 116 -> 117.

Status 2026-09-16 (116)

Secretary Journal 116 (versionCode 116): Single-Flavor-Journal (offline-first, sync als Add-on). Die Flavor-Duplikation (remote/local) ist in einem einzigen Code-Strang aufgehoben: localMode = !repo.isConfigured(); ohne Konto ist die App rein lokal (Cache als einzige Quelle), nach Login kommt CalDAV als Add-on dazu (erster Connect re-homt lokal angelegte Uids auf den Server-Pfad und lädt sie hoch; der gemergte Stand ersetzt den Cache; Logout behält den Store). Enthalten: JournalTransfer, die gemeinsame SecretarySettingsScreen (onLogin/connectLabel-Parameter, Einträge-Sektion „Verbinden"), settings_connect_*-Strings DE/EN, TutorialPrefs gelöscht, Flavor- Verzeichnisse, des Buildsystems Single-APK. Außerdem: keine Status-Bar-Hiding-Änderungen. versionCode 115 -> 116.

Status 2026-09-16 (115)

Secretary Journal 115 (versionCode 115): Version bump nach Reset auf v93. Der trunk wurde auf den Stand vor dem v94-Flavour-Merge (20699bfc3a, v93) zurückgesetzt; die Flavour-Merge-Linie (v94–v114) samt merge-redo liegt jetzt versteckt/geschlossen auf dem Abzweig abandoned-flavor-merge. Versionierung folgt weiter dem Repository-Stand (115 > 114, damit das Build-System ein frisches Artefakt liefert). versionCode 114 -> 115.

Status 2026-09-14 (93)

Secretary Journal 93 (versionCode 93): Einstellungen: „Zufalls-Zeitfenster" → „Ruhezeit" umbenannt, Auswertungs-Karte entfernt, PayPal-Unterstützungs- Karte hinzugefügt. Die Einstellung für das Zeitfenster, in dem keine Erinnerungen stattfinden, heißt jetzt „Ruhezeit" (DE) / „Quiet time" (EN) – der Hinweistext beschreibt den invertierten Zweck (keine Erinnerungen und Vorschläge), der Standardwert ist 22:00–07:00 (statt 07:00–22:00). Die Auswertungs-Karte (Tag-Intervall-Pills 7/14/30/90/365 Tage) ist aus beiden Settings-Screens (remote + local) entfernt; der Bewertungszeitraum ist auf 30 Tage hardcodiert (JournalRepository.evaluationWindowDays(), Default bleibt 30). Importierte/verbleibende SharedPreferences-Werte werden weiter gelesen. Die PillRow-/Pill-Imports und der evalWindowDays-State sind aus beiden SettingsScreens entfernt. Unterm Abschnitt „Lizenz & Quellen" gibt es einen neuen Abschnitt „Unterstützen" (DE) / „Support" (EN) mit einem Hinweis-Text und einem klickbaren PayPal-Link (https://www.paypal.com/paypalme/beowulfof). Die Tutorial-Seite „Vorlagen & Erinnerungen" (tutorial_templates_body, DE+EN) erwähnt die Ruhezeit/Quiet time als Zeitraum ohne Erinnerungen und Vorschläge. RandomWindowSettings-KDoc aktualisiert. versionCode 92 -> 93.

Status 2026-09-14 (92)

Secretary Journal 92 (versionCode 92): Trigger-/Skill-Editor auf gesammelte-Werte-Dropdown umgestellt; Korrelation/Karten entfernt; nach Trigger-Erfassung Skill-Vorschlag als Erinnerung. Im gemeinsamen TendencyTextBody (beide Flavor) ist das Freitextfeld für Trigger/Skill jetzt ein editierbares Dropdown (GatheredValueField: ExposedDropdownMenuBox + ExposedDropdownMenuAnchorType.PrimaryEditable, gefilterte Vorschläge live, take(8), sortiert nach Häufigkeit aus vm.gatheredData des jeweiligen Typs) – neuer Text bleibt frei eingebbar (updateEntryText), Tippen übernimmt einen gesammelten Wert. Entfernt sind die drei Editor-Karten/-Sektionen: TriggerCorrelationSection („Bewährte Gegenmittel"/„Risiko-Muster"), TriggerSkillProposalsSection („Skill-Vorschläge" mit Kopieren) und SkillCorrelationSection („Auslöser der letzten %d Tage"); dadurch entfallen auch editorCorrelation in beiden ViewModels sowie in ProposalEngine der komplette v40-Korrelationsblock (TriggerSkillLink, CorrelationPattern, correlationPattern, correlateSkillAt, correlateTriggerWithText, skillUid; proposeSkillsAfterTrigger + SkillProposal + entryTimeMs bleiben). Stattdessen: Beim Speichern eines Trigger-Eintrags (keine Vorlage) setzt saveEntry nach dem Persistieren den Top Skill-Vorschlag (proposeSkillsAfterTrigger gegen die aktualisierten entries) in die neuen One-Shot-State skillReminderProposal/ skillReminderTriggerText; der NavGraph zeigt darüber (Box-Overlay über dem NavHost, Route-unabhängig) den SkillReminderDialog („Trigger erfasst – Skill-Vorschlag"): Body mit Trigger-Text, Skill-Text, %dx · ↗ n · Stimmung besser n; „Skill erfassen" ruft adoptSkillReminder() (= öffnet openSkillEntryForDate(LocalDate.now()) + copy(text = Vorschlag) und navigiert zum Editor), „Verwerfen" ruft dismissSkillReminder(). DE/EN-Strings: corr_* + prop_* gelöscht; neu edit_gathered_hint/ edit_gathered_empty/remind_skill_title/remind_skill_body/ remind_skill_add/remind_skill_dismiss; tutorial_trigger_body/ tutorial_skill_body (Editor-Korrelations-Claim entfernt). Beide Flavor kompilieren sauber (v71-Standard). versionCode 91 -> 92.

Status 2026-09-14 (91)

Secretary Journal 91 (versionCode 91): Tutorial um „Gesammelte Trigger & Skills"-Seite erweitert. Das interaktive Tutorial (v85/v84, inzwischen 15 Seiten) bekommt nach der Statistik-Seite eine neue Seite „Gesammelte Trigger & Skills" (Icon Icons.Filled.CollectionsBookmark, tutorial_gathered_title/tutorial_gathered_body, DE+EN): Sie erklärt den GatheredScreen – der Screen sammelt jeden Trigger- und Skill-Text aus dem Journal, Tippen benennt einen Wert um, Gedrückthalten führt ihn mit einem anderen zusammen, beides wirkt auch auf alle bisherigen Einträge (rückwärts); erreichbar über Einstellungen → „Gesammelte Trigger & Skills". Kein TutorialTry-Action-Button (die Seite öffnet den Screen nicht, nur Textkarte). Entfernbarer Zugriff unverändert über den Tutorial-Button in beiden Settings-Screens bzw. den Auto-Start der lokalen Edition. versionCode 90 -> 91.

Status 2026-09-14 (90)

Secretary Journal 90 (versionCode 90): Gesammelte Werte: Bedienung auf Tipp/Gedrückthalten umgestellt. Im GatheredScreen (v89) ersetzt eine naturlichere Gesten-Bedienung die Checkboxen und Buttons: ein kurzer Tap auf einen Eintrag öffnet direkt den Umbenennen-Dialog, ein langer Druck öffnet ein Dropdown-Menü (wie ItemContextMenu, combinedClickable), das alle anderen gesammelten Werte desselben Typs auflistet – Auswahl führt diesen Wert mit dem angetippten zusammen (mergeGatheredTexts mit einem Quelltext, das bestehende Einträge via copy(text=…) + pushAllEntries()/persist() rückwirkend umschreibt). Die bisherigen Zeilen-Checkboxen, der „%d ausgewählt"-Zähler und der Zusammenführen-Button samt MergeDialog (mit Ziel-Textfeld) sind entfernt; je Sektion zeigt eine neue Hinweiszeile (gathered_gesture_hint) die Gesten. Entfernte DE/EN-Strings: gathered_merge, gathered_merge_title, gathered_merge_target, gathered_merge_hint, gathered_select_cd, gathered_selected_count; neu gathered_merge_with/gathered_gesture_hint. versionCode 89 -> 90.

Status 2026-09-14 (89)

Secretary Journal 89 (versionCode 89): Gesammelte Trigger & Skills wieder eingeführt (fresh, rein aus den Einträgen abgeleitet) + gewichtete Skill-Vorschläge nach Trigger. In beiden Einstellungen-Screens (remote + local) gibt es im neuen Abschnitt „Gesammelte Trigger & Skills" einen Button „Gesammelte Werte verwalten", der den neuen Screen GatheredScreen (Route gathered, wie die anderen Screens mit ScreenHeader) öffnet: Je Liste (Trigger/Skill) zeigt er jeden distinct Freitext mit Anzahl (n×), letztem Auftreten (dd.MM.yyyy) und — aus dem neuen Wiederholungs-Scan — durchschnittlichem Abstand in Tagen (Ø alle X Tage). Die Daten kommen nie serverseitig, sondern live aus dem Eintrags-Cache über die neue reine GatherEngine (GatheredItem: entryType/text/count/lastSeen) und ProposalEngine.scanRecurringPatterns (RecurringPattern: occurrences/averageGapDays/lastOccurrence) — kein kuratiertes GatheredStore, die Listen sind per Definition deckungsgleich mit der Historie (Abkehr vom v59-„GatheredStore"-Konzept). In der Zeile kann man per Checkbox mehrere Werte fürs Zusammenführen auswählen sowie jeden Wert umbenennen: Beides wirkt als Rückwärts-Anpassung in allen historischen Einträgen (entries = entries.map + copy(text = …), remote danach pushAllEntries(), local withContext(Dispatchers.IO) { persist() }; neu in beiden ViewModels renameGatheredText/mergeGatheredTexts). Der Trigger-Editor zeigt unter der bestehenden Korrelation eine neue Sektion „Skill-Vorschläge" (TriggerSkillProposalsSection, getrieben von ProposalEngine.proposeSkillsAfterTrigger): Sie bewertet Skills, die in den FOLLOWUP_WINDOW_DAYS (3 Tage) auf einen Trigger gleichen Texts folgten, mit weight = Belege + 0.5 × positive Belege, wobei ein Beleg positiv ist, wenn der Trigger Tendenz hoch bekam oder die Stimmung nach dem Skill höher war als vor dem Trigger (Mood-numericValue, regelbasierter Vergleich über den nächstliegenden Mood-Eintrag); pro Vorschlag zeigt die Zeile Meta n× · ↗ n · Stimmung besser n (proof/tendencyUp/moodLift) und den Rang, Tippen kopiert den Text in die Zwischenablage (Toast). DE/EN-Strings settings_section_gathered/settings_gathered_*/gathered_* und prop_* ergänzt. versionCode 88 -> 89.

Status 2026-09-13 (88)

Secretary Journal 88 (versionCode 88): Kategorie-Parsing gehärtet + Wiederholungs-Korrektur übernommen (secretary-common-android v0.26.0). Die gemeinsame Bibliothek baut jetzt mit dem CATEGORIES-Escape-Fix: Der VJournal.parseNote-Fix (v0.25.0) – Splitt der CATEGORIES-Liste nur an unescaped-gespeicherten Kommas statt an jedem , – sorgt dafür, dass Wochentags-Regeln (RRULE:FREQ=WEEKLY;BYDAY=MO\,WE\,FR) beim erneuten Öffnen des Wiederholungs-Editors wieder vollständig mit allen ausgewählten Tagen gelesen werden. v0.26.0 verallgemeinert dasselbe Escaping-Verhalten auf VTODO/VEVENT/VCARD (betrifft Tasks/Calendar/ Contacts, nicht das Journal). versionCode 87 -> 88.

Status 2026-09-13 (87)

Secretary Journal 87 (versionCode 87): Lokale APK heißt jetzt journal-<version>.apk. Seit v81 teilen beide Flavor dieselbe applicationId (org.beowulf.secretary.journal) und denselben App-Namen „Journal" — nur das APK-Artefakt des Buildsystems der lokalen Edition hieß weiterhin secretary-journal-local-<version>.apk. Neu wird die lokale Edition unter journal-<version>.apk in das Paket-Repository kopiert (das Buildsystem: die Bauanzeige nennt secretary-journal-<version>.apk für Remote und journal-<version>.apk für Local, der Copy-Schritt benutzt journal-{version}.apk); die Remote-Edition bleibt unverändert secretary-journal-<version>.apk. Alte secretary-journal-local-*-Artefakte im Repository bleiben unberührt. versionCode 87 == versionName 87 (local: 87-lokal).

Status 2026-09-13 (86)

Secretary Journal 86 (versionCode 86): Fixes im interaktiven Tutorial (v85). Zwei Fehler behoben: (1) Der „Ausprobieren"-Button begrenzte seine Höhe fest auf 48dp und schnitt dadurch umbrechende/mehrzeilige Labels ab — ersetzt durch defaultMinSize(minHeight = 48.dp), sodass die Taste mit dem Text wächst. (2) Beim Verlassen des Editors über den Zurück-Pfeil (der Editor wird vom Tutorial aus geöffnet) landete man auf der ersten statt der vorherigen Tutorial-Seite: Die Seitenvariable page nutzte remember und ging beim Wegkomponieren der Tutorial-Route (Nutzen von Routes.EDIT) verloren. Mit rememberSaveable bleibt der Seitenindex über die Navigation erhalten und das Tutorial kehrt auf dieselbe Seite zurück, von der aus der Durchlauf gestartet wurde. versionCode 86 == versionName 86 (local: 86-lokal).

Status 2026-09-13 (85)

Secretary Journal 85 (versionCode 85): Interaktiver Tutorial-Durchlauf („Ausprobieren"). Auf jeder Eintrags-Tutorialseite (Highlights, Stimmung, Stuhl & Urin, Medikamente, Essen & Getränke, Trigger, Skill) gibt es unter der Textkarte einen Button „Eintrag anlegen und ausprobieren" (tutorial_try_entry), auf der Vorlagen-Seite den Button „Tägliche Highlights-Vorlage anlegen" (tutorial_try_template). Beide öffnen den Editor vorausgefüllt direkt über dem Tutorial (Route EDIT wird auf den Tutorial-Stapel gelegt; Speichern/Abbrechen führt zurück ins Tutorial). Dafür bekommt TutorialScreen den neuen Callback onTry(TutorialTry) und jedes TutorialPage ein optionales tryAction-Attribut; NavGraph mappt die Aktion: Eintragsseiten rufen das jeweilige vm.open*EntryForDate (LocalDate.now(), Highlights weiterhin find-or-create/fortführen) auf, die Vorlagen-Seite legt einen frischen TEXT-Entwurf mit isTemplate = true und RRULE FREQ=DAILY an (createNewTextEntry + setEditingTemplate(true)

Status 2026-09-13 (84)

Secretary Journal 84 (versionCode 84): Tutorial automatisch beim ersten Start (lokale Edition) + Eintragstypen-Walkthrough. Nur die lokale Edition öffnet das Tutorial beim ersten App-Start automatisch (Route tutorial, TutorialPrefs in data/: Flag tutorial_auto_started in den flavor-eigenen Prefs secretary_journal_local bzw. secretary_journal; NavGraph navigiert per LaunchedEffect(loggedIn) nur bei BuildConfig.FLAVOR == "local" und setzt das Flag beim Anzeigen, danach bleibt es im Einstellungen- Button erreichbar). Das Tutorial ist auf 14 Seiten erweitert und geht seit der Aufteilung der bisherigen Eintragstypen-Übersicht durch alle Eintragstypen: Highlights (nur einmal pro Tag, wird beim erneuten Öffnen fortgeführt – explizit im tutorial_highlights_body), Stimmung (fünf Stufen, auch mehrmals täglich), Stuhl & Urin (Bristol 1–7 / Armstrong 1–8), Medikamente (Wirkstoff/Darreichungsform/Dosis, Erinnerung), Essen & Getränke (kJ/ml), Trigger und Skill (je mit Tendenz). Die Folge-Seiten (Willkommen, Einträge anlegen, Übersicht, Auswertung, Vorlagen/Erinnerungen, Statistik, Sicherheit/ Sicherung) bleiben. Die bisherigen tutorial_0_*…tutorial_6_*-Strings sind durch sprechende Namen ersetzt (tutorial_welcome_*…tutorial_security_*). versionCode 84 == versionName 84 (local: 84-lokal).

Status 2026-09-13 (83)

Secretary Journal 83 (versionCode 83): Fix: Deprecation-Warnung im Tutorial. Die MenuBook-Icon auf der Willkommensseite des Tutorials verwendet jetzt die AutoMirrored-Variante (Icons.AutoMirrored.Filled.MenuBook statt des deprecated Icons.Filled.MenuBook) – beide Flavor kompilieren wieder ohne Warnungen (v71-Standard). Kein funktionaler Unterschied, nur der Referenzwechsel für die RTL-Auto-Mirroring-Warnung. versionCode 83 == versionName 83 (local: 83-lokal).

Status 2026-09-13 (82)

Secretary Journal 82 (versionCode 82): In-App-Tutorial. In beiden Einstellungen-Screens (remote + local) gibt es im neuen Abschnitt „Tutorial" einen Button „Tutorial starten", der einen seitenbasierten Tutorial-Screen (Route tutorial, TutorialScreen in ui/, wie die anderen Screens mit ScreenHeader, Zurück/Weiter/Fertig-Navigation und Punkt-Indikator) öffnet. Sieben Seiten führen durch die Funktionen: Willkommen (Server/CalDAV oder lokal), Einträge anlegen (+ bzw. Smiley, Datum + Uhrzeit), Eintragstypen (Highlights, Stimmung, Stuhl/Urin, Medikamente, Essen/Getränke, Trigger/Skill mit Tendenz), Stimmung & Auswertung (fünf Stufen, einstellbares Fenster 7–365 Tage), Vorlagen & Erinnerungen (fest/zufällig, Medikamenten-Erinnerungen), Trigger & Skills (Statistik, bewährte Gegenmittel, Risiko-Muster) und Sicherheit & Sicherung (Passwort-Verschlüsselung, Biometrie, Export/Import, Klartext-Bericht). DE/EN-Strings settings_section_tutorial/settings_tutorial_hint/settings_tutorial_button und tutorial_* ergänzt. versionCode 82 == versionName 82 (local: 82-lokal).

Status 2026-09-13 (81)

Secretary Journal 81 (versionCode 81): Lokale Edition heißt nur noch „Journal“ – Name und Paket. Der app_name-Override der lokalen Edition (app/src/local/res/values/strings.xml) lautet nicht mehr „Journal lokal“, sondern „Journal“ – identisch zur Remote-Edition. Außerdem trägt die lokale Edition jetzt dasselbe applicationId org.beowulf.secretary.journal (statt org.beowulf.secretary.journal.local), die versionNameSuffix- Versionierung bleibt (81-lokal); die Flavor-Daten bleiben getrennt (secretary_journal_local-Prefs). versionCode 81 == versionName 81 (local: 81-lokal).

Status 2026-09-13 (80)

Secretary Journal 80 (versionCode 80): Emoji-Gesichter statt kawaii- Canvas-Smiley. Die gezeichneten kawaii-Stimmungsgesichter (KawaiiMoodFace) sind ersetzt: MoodEmojiFace zeigt jetzt nur noch das echte Unicode-Emoji (Mood.emoji, dieselben Emojis wie in Eintragslisten und Editor) proportional zur Kachelgröße (maxHeight * 0.78). Betroffen sind das Hero- Smiley (dominante Stimmung, 150dp) und die Mood-Einträge in der Liste/ Vorlagenliste (44dp). Damit sind Stimmung, Gesichtsausdruck und -Farbgebung identisch zu den Emojis, die bei der Auswahl/Listung der Einträge verwendet werden. versionCode 80 == versionName 80 (local: 80-lokal).

Status 2026-09-12 (79)

Secretary Journal 79 (versionCode 79): Stimmungs-Gesichter auf Kachelgröße vereinheitlicht. In den Eintragszeilen (DayEntryRow) wurden die kawaii-Stimmungsgesichter von 52dp auf 44dp reduziert – dieselbe Größe wie die farbigen Typ-Kacheln der übrigen Einträge und wie der danebenstehende Tendenz-Pfeil; der isMood-Sonderfall für die Bildgröße ist entfernt (KawaiiMoodFace skaliert proportional). versionCode 79 == versionName 79 (local: 79-lokal).

Status 2026-09-12 (78)

Secretary Journal 78 (versionCode 78): Liste zurückgebaut: Tag+Datum als eigene Kopfzeile, alte Tendenz-Pfeile, Eintrag = Icon + Pfeil + Text. Der kräftige Canvas-Pfeil TendencyArrow aus v77 ist wieder entfernt – alle Tendenz-Anzeigen nutzen wieder das dünne Material-Icon tendencyIcon (TrendingUp/TrendingDown mit tendencyColor-Tint): Eintrags- und Vorlagen-Zeilen, das Tendenz-Badge am Hero-Smiley und die beiden Korrelations-Zeilen im Editor (Trigger-Row, Skill-Liste samt zugehöriger semantics/CircleShape-Imports). Die Tageszeile (DayListRow) hat keine 92dp-Indexspalte mehr: Wochentag + Datum stehen als eigene vollbreite Kopfzeile (heute * fett unterstrichen primär, Sa/So rot, Hintergrund je isShadedDay täglich alternierend), darunter alle Einträge dieses Datums. Jede Eintragszeile (DayEntryRow) ist Icon links, direkt daneben der Tendenz-Pfeil in gleicher Größe (44dp-Kachel bzw. 52dp-Kawaii-Gesicht, Mood ohne Tendenz), dann der Text im restlichen Zeilenraum (mehrzeiliger Umbruch). Highlights (TEXT) stellen jede der drei Felder in einer eigenen Zeile dar (goodOne/goodTwo/goodThree, leere Felder übersprungen) bei nur einem Icon pro Eintrag; Zeit (entryTimeText) als zweite Zeile. Die Vorlagen-Zeile nutzt denselben Icon+Pfeil+Text-Aufbau ohne Disc/Overlay. versionCode 78 == versionName 78 (local: 78-lokal).

Status 2026-09-12 (77)

Secretary Journal 77 (versionCode 77): Liste verfeinert: Zeit statt Datum, kräftige Tendenz über dem Icon, tägliche Schattierung, Vorlagen-Liste im gleichen Stil. Da die Einträge in der Hauptansicht chronologisch nach Tag gruppiert sind (Tagesindex links), zeigt jede Eintragszeile (DayEntryRow) nur noch die Uhrzeit (entryTimeText, HH:mm, leere Zeile bei Datum-ohne-Zeit-Einträgen) statt dd.MM.yyyy, HH:mm. Die Tendenz sitzt nicht mehr rechts am Zeilenende, sondern als kräftiger Pfeil über der unteren rechten Ecke des Entry-Icons auf einem opaken runden surface-Disk (EntryIconTile: 52dp-Kawaii-Gesicht bzw. 44dp-Typ-Kachel, Disk ≈ tile/2.4, Pfeil ≈ tile/2.8). Der Pfeil ist kein dünnes Material-Icon mehr, sondern der neue gemeinsame TendencyArrow (Canvas: dicker runder Schaft mit 26 %-Strichbreite plus gefüllter dreieckiger Spitze ↗/↘, in JournalTypeUi) — konsistent überall: Eintrags-Kacheln und Vorlagen-Zeilen, das Tendenz-Badge unten rechts am großen Smiley (Hero) und die zwei Korrelations-Zeilen im Editor (Trigger-Row, Skill-Liste); alle tendencyIcon-Material-Aufrufe sind durch TendencyArrow ersetzt. Der Zeilen-Hintergrund wechselt nicht mehr je ISO-Woche, sondern täglich (isShadedDay, gerades Epoch-Day hell/dunkel wie bisher, benachbarte Tage alternieren). Die Vorlagen-Liste ist im selben Stil umgebaut (TemplateListRow ohne Card): Icon-Kachel mit optionaler Tendenz-Überlagerung, einzeiliger Titel, „Nächstes Mal"- Zeile und der Play-Button „Jetzt eintragen"; die bisherigen Karten-Umrandung und PaddingValues/Card-Import sind entfernt. versionCode 77 == versionName 77 (local: 77-lokal).

Status 2026-09-12 (75)

Secretary Journal 75 (versionCode 75): Kalender-Tagesliste statt Eintragskarten + 5-Stufen-Stimmung. Die Hauptansicht zeigt jetzt eine Liste wie im secretary-calendar: Die Einträge sind nach Datum gruppiert (neueste zuerst, neueste oben), links steht der Tagesindex (Wochentag- Kürzel plus Tag, heute mit *-Präfix fett unterstrichen in Primärfarbe), Sa/So und das Datum sind rot (error-Farbe) und der Zeilen-Hintergrund wechselt hell/dunkel je ISO-Kalenderwoche (gerade Woche heller, ungerade dunkler, isShadedWeek). Rechts neben dem Index stehen die Einträge: Stimmungs-Einträge zeigen die kawaii-Gesichter nun deutlich größer (52dp, KawaiiMoodFace), andere Typen ihr Icon in farbiger Kachel, daneben Titel (mit Umbruch, mehrzeilig), Zeitstempel und die Tendenz rechts; der Wort-Umbruch erlaubt mehrzeilige Zeilen. Dafür wird die Eintragsliste in JournalCarouselScreen nicht mehr als flache EntryListRow-Karten (maxLines = 1) gezeichnet, sondern je Tag (DayListRow/DayEntryRow) mit Trennlinie. Zudem ist die Stimmung auf 5 Stufen erweitert: Mood hat neu VERY_SAD (💧😭) und VERY_HAPPY (😄) zwischen den bisherigen Werten, JournalTypeUi liefert Icons/Farben/Labels für alle fünf, beide ViewModels nutzen die Schwellen (≥3.5/≥2.5/≥1.5/≥0.5 → veryHappy/happy/normal/sad/verySad, happy = HAPPY||VERY_HAPPY, sad = SAD||VERY_SAD), KawaiiMoodFace zeichnet fünf Gesichter (verySad: großer Frown + 2 Tränen + hängende Lider, sad: Frown + 1 Träne, normal: sanftes Lächeln, happy: offenes Lächeln, veryHappy: geschlossene Freude-Augen „^ ^" + breites Lächeln mit Zunge) und der Stimmungs-Editor zeigt die fünf Zellen in FlowRow (wrap-fähig). DE/EN-Strings für die neuen Stufen ergänzt (mood_very_sad/mood_very_happy), mood_happy/mood_neutral angepasst (Gut/Good, Normal/Neutral). Alte Einträge mit mood:sad|normal|happy bleiben lesbar. versionCode 75 == versionName 75 (local: 75-lokal).

Status 2026-09-12 (74)

Secretary Journal 74 (versionCode 74): Bäckchen entfernt. Aus dem KawaiiMoodFace aus v73 sind die rosigen Blush-Bäckchen entfernt – das Gesicht besteht nur noch aus Gesichts-Disc, Augen und Mund (Zunge bleibt). versionCode 74 == versionName 74 (local: 74-lokal).

Status 2026-09-12 (73)

Secretary Journal 73 (versionCode 73): Kawaii-Smiley statt Mood-Orbit-Ring. Der in v72 eingeführte Mood-Orbit-Ring (drei Emojis auf proportionalen Kreisbögen) ist wieder entfernt – der Verweis auf einen stilisierten Mood-Tracker-UI macht deutlich, dass der Ring der gewünschten Ästhetik nicht entsprach. Stattdessen zeichnet KawaiiMoodFace (Canvas, reines Compose) für die dominante Stimmung ein kawaii-artiges Gesicht in der jeweiligen Mood-Farbe: weiches Gesichts-Disc mit Ton-Ring, große glänzende Augen mit Spiegelpunkten (traurig: hängende Lider + Träne), rosige Bäckchen und stimmungsabhängiger Mund (happy: breites Lächeln mit Zunge, normal: sanftes Lächeln, sad: Frown + Teardrop). Der Platzhalter „–" bleibt bei fehlenden Stimmungsdaten, das Tendenz-Badge unten rechts und die Jung/Alt-Zählzeile unverändert. Unbenutzte Imports (Icons.Mood/MoodBad/SentimentNeutral, border, offset, cos/sin) entfernt. versionCode 73 == versionName 73 (local: 73-lokal).

Status 2026-09-12 (72)

Secretary Journal 72 (versionCode 72): Typewriter-Vereinheitlichung und Mood-Orbit-Ring. Die Stimmungskennzahl im Karussell ist kein stimmungsloser Platzhalter mehr, sondern nutzt displayLarge (Special Elite). Zeitstempel (labelMedium) und Vorlagen-Vorschau (labelSmall) erscheinen in der Monospace-Metadaten-Schrift. Die Kalender-Tageszahlen verwenden die Typewriter-Font (heute titleMedium fett, sonst titleSmall). Der bisherige einfache Mood-Donut wird durch den Mood-Orbit-Ring ersetzt: drei Mood-Emojis (happy oben, normal unten-rechts, sad unten-links) sitzen auf dem Ring; proportionale farbige Kreisbögen zeigen die Verteilung, die dominante Stimmung ist als Chip vergrößert und hervorgehoben. Reines Canvas, keine neuen Abhängigkeiten. versionCode 72 == versionName 72 (local: 72-lokal).

Status 2026-09-11 (71)

Secretary Journal 71 (versionCode 71): Deprecation-Warnungen entfernt. Zwei Kotlin-Warnungen beim Debug-Build sind behoben (kein @Suppress, Ursachen-Lösung): CrashReporter liest die Version über PackageInfoCompat.getLongVersionCode statt des deprecated PackageInfo.versionCode (Int-Feld, seit API 28 deprecated) und LocalePrefs.wrap erzeugt die Locale über Locale.forLanguageTag statt des deprecated Locale(String)-Konstruktors (Java 19). Beide Flavor kompilieren ohne Warnungen; das JSON-Report-Feld versionCode enthält weiterhin eine Zahl (nun Long). versionCode 71 == versionName 71 (local: 71-lokal).

Status 2026-09-11 (70)

Secretary Journal 70 (versionCode 70): Editor-Vereinheitlichung. Eintragsfelder sind jetzt homogen: Bei Essen/Snack steht der Text (Was gegessen?) vor der Energie (kJ) — beim Getränk Name vor Menge (ml), Werte kommen überall nach der Beschreibung. Die Tendenz-Auswahl ist ans untere Ende des Editors gewandert und steht direkt über dem Speichern- Button (IME-Padding bleibt erhalten, beides ist bei offener Tastatur scrollbar erreichbar). Alle Chip-Reihen (Essensart, Excreta-Art, Darreichungsform, Tendenz) nutzen jetzt FlowRow statt horizontalem Scroll, sodass Chips nie aus dem sichtbaren Bereich laufen. Die Essensart hat nur noch drei Chips (Mahlzeit/Snack/Getränk) — „Keine" ist entfernt; das Abwählen der Auswahl funktioniert weiterhin per erneutem Tippen auf den gewählten Chip. Die gekapselten FilterChip-Funktionen bleiben unverändert. versionCode 70 == versionName 70 (local: 70-lokal).

Status 2026-09-11 (69)

Secretary Journal 69 (versionCode 69): Version bump. Property bump nach v68 – Versionierung folgt dem Repository-Stand (der das Buildsystem Build-Manager überspringt die Erstellung, wenn eine Ziel-APK gleicher Version bereits im Repo liegt). versionCode 69 == versionName 69 (local: 69-lokal).

Status 2026-09-11 (68)

Secretary Journal 68 (versionCode 68): Fix: „Eintragen" einer fälligen Vorlage tut nichts (v64). Der Accept-Button der Vorlagen-Benachrichtigung lief als PendingIntent.getActivity direkt auf die MainActivity; die Entwurfs-Anlage, die Benachrichtigungs-Verwerfung und das Neu-Armen wurden aber seit v64 ausschließlich im Broadcast-Pfad (TemplateReceiver.handleAccept) erledigt, den niemand mehr auslöste. Die Pending-Edit-Queue blieb leer → vm.handleTemplateAccept kehrte bei drainPendingEdit ?: return zurück und die Benachrichtigung blieb stehen. Neu ist der Accept-Button weiterhin ein activity PendingIntent auf MainActivity (zuverlässig, da Notification-Taps von den Android-Background-Activity-Start-Einschränkungen ausgenommen sind); die Entwurfs-Klonung, die Benachrichtigungs-Verwerfung und das Neu-Armen sind aber aus dem unerreichbaren Broadcast-Pfad in eine neue Companion-Function TemplateReceiver.performAccept(context, uid) verlagert, die beide MainActivitys (remote + local) in handleTemplateAccept vor vm.handleTemplateAccept aufrufen – dadurch wird die Edit-Queue korrekt befüllt und der vorausgefüllte Editor öffnet sich zuverlässig. Der ACTION_TEMPLATE_ACCEPT-Zweig im Broadcast-Empfänger ist entfernt. versionCode 68 == versionName 68 (local: 68-lokal).

Status 2026-09-11 (67)

Secretary Journal 67 (versionCode 67): Crash-fix: System-Dateidialog (und alle Activity-Result-Launcher) unter FragmentActivity. Beide Flavor-MainActivitys erweitern jetzt androidx.activity.ComponentActivity (statt FragmentActivity, das seit v28 für BiometricPrompt benötigt wurde). Hintergrund: androidx.activity's ActivityResultRegistry vergibt seit 1.2.0 Request-Codes in den oberen 16 Bits (0x10000–Int.MAX), FragmentActivity. startActivityForResult erzwingt aber den 0–65535-Bereich (checkForValidRequestCode, „Can only use lower 16 bits for requestCode"). Dadurch crashte jeder Launcher- Start deterministisch – nachgewiesen in zwei Crash-Reports der FP5 (ReportCard.kt:129, „Erstellen" des Berichts öffnet nicht den Dateidialog): Betroffen waren der Bericht (CreateDocument("text/plain")) sowie auch Export/Import (CreateDocument/OpenDocument). ComponentActivity führt diese Prüfung nicht aus; die App ist reine Compose ohne Fragments. Damit ist auch das Biometrie-Hosting kein Problem mehr: rememberBiometricPrompt nutzt jetzt die neue rememberAuthenticationLauncher-API (androidx.biometric:biometric-compose 1.4.0-alpha07, basierend auf registerForAuthenticationResult(), der Nachfolger von BiometricPrompt im old-Style, der nur FragmentActivity/Fragment kennt; ersetzt die alte BiometricPrompt(FragmentActivity, …)-Konstruktion aus v28). biometricAuthRequest(context, title, subtitle, crypto) baut einen Class-3-Authentifizierungsrequest (Abbruch = CustomOption-Fallback statt negativem Button); enc_enable_biometric_title/-sub, unlock_title/-sub und der Zeichensatz bleiben unverändert. BiometricCommon.findFragmentActivity/ findActivity entfallen. versionCode 67 == versionName 67 (local: 67-lokal).

Status 2026-09-11 (66)

Secretary Journal 66 (versionCode 66): Klartext-Bericht für den Arzt. In beiden Einstellungen-Screens (remote + local) gibt es im Abschnitt „Sicherung" unter Export/Import eine neue Karte „Bericht" (ReportCard, ui/crypto/): Ein Klick auf „Bericht erstellen" öffnet einen Dialog, in dem man die einzubeziehenden Eintragstypen per Checkbox einschließen/ ausschließen kann (Highlights, Stimmung, Excreta, Medikamente, Essen, Trigger, Skill, Standard: alle); „Erstellen" öffnet den System-Dateidialog (CreateDocument("text/plain"), Vorschlag journal-report-<Datum>.txt) und schreibt einen Zeilen-basierten Klartext-Bericht aller passenden Einträge. Der Bericht (journalReportText in ui/JournalReport.kt, abgerufen über vm.reportData(uri, includedTypes) in beiden ViewModels): sortiert chronologisch (älteste zuerst), schließt Vorlagen aus, ist immer Klartext (bei aktiver Verschlüsselung werden die Einträge vorher JournalTransfer.decryptEntries()-entschlüsselt; bei gesperrtem Journal erscheint der Hinweis report_locked statt der Datei) und führt je Eintrag Zeitpunkt (dd.MM.yyyy, HH:mm) + Typ-Label und darunter alle Felder aus (drei Gute-Dinge-Zeilen, Stimmung mit Emoji, Stuhl/Urin mit Bristol-/Armstrong- Beschreibung, Medikament mit Dosis und Grund, Essen/Getränk mit kJ bzw. ml, Trigger/Skill-Text, optional Tendenz). Zweck: die Daten einfach und lesbar einem Arzt zur Auswertung zu übergeben. DE/EN-Strings report_* + vm_report_created. versionCode 66 == versionName 66 (local: 66-lokal).

Status 2026-09-11 (64)

Secretary Journal 64 (versionCode 64): Vorlagen-Erinnerung „Eintragen" öffnet den Editor vorausgefüllt statt den Eintrag sofort anzulegen. Bisher legte das Accept einer fälligen Vorlage (TemplateReceiver) einen fertigen Eintrag an (Clone in die Accept-Queue, dann via drainPendingTemplates in beiden ViewModels persistiert). Neu legt Accept nur einen Entwurf ab: TemplateReceiver.handleAccept klont die Vorlage (neue uid, isTemplate=false, rrule="", randomSchedule=null, Datum heute / occurredAt=jetzt) in die neue Pending-Edit-Queue (PendingTemplateQueue.edits, ersetzt die Accept-Queue samt ACTION_ACCEPTED-Broadcast), armt das nächste Vorkommen neu, verwirft die Benachrichtigung und startet die App (Activity-PendingIntent

Status 2026-09-11 (63)

Secretary Journal 63 (versionCode 63): „Nächstes Mal" für Zufalls-Vorlagen zeigt jetzt den nächsten echten Zufalls-Slot statt des RRULE-Basisauftretens. Der Vorlagen-Zeilen-Label (nextTemplateOccurrence in JournalCarouselScreen) berechnete bisher für jede Vorlage den nächsten RRULE-Auftritt (TemplateAlarmScheduler.nextOccurrence) – bei einer täglichen Wiederholung mit Basiszeit in der Vergangenheit (Vorlage z. B. heute um 14:00 angelegt, „Nächstes Mal" = morgen 14:00). Die Zufalls-Alarme für heute waren trotzdem korrekt bewaffnet (3 deterministische Slots im Einstellungs-Fenster), aber unsichtbar. Neu nutzt der Label für Vorlagen mit randomSchedule den frühesten bewaffneten Zufalls-Slot (TemplateAlarmScheduler.nextRandomFire, gleiche Fenster-/Vorkommens-Logik wie arm inkl. isOccurrenceDay), sodass z. B. eine heute angelegte „Stimmung"-Vorlage mit 3×/Tag + täglich „Nächstes Mal: <heute, HH:mm>" zeigt; erst wenn das heutige Fenster bereits vorbei ist, wandert der Eintrag auf den nächsten Vorkommens-Tag. FIXED-Vorlagen (RRULE) zeigen unverändert das RRULE-Auftreten. versionCode 63 == versionName 63 (local: 63-lokal).

Status 2026-09-11 (62)

Secretary Journal 62 (versionCode 62, auf secretary-common-android v0.24.0): Entweder fixe Zeit oder Zufall mit Anzahl pro Tag + Zeitfenster in den Einstellungen (Standard 07:00–22:00), Wiederholung zusätzlich. RandomSchedule ist auf den reinen Zähler geschrumpft (N = X zufällige Zeiten pro Tag; Persistenz rand:N, Export-Schema 10); das Zeitfenster ist kein Eintrags-Attribut mehr, sondern eine globale Einstellung in beiden Settings-Screens (RandomWindowSettings, Abschnitt „Zufalls-Zeitfenster" mit Von/Bis-Zeitpicks, Werte als Minuten-seit-Mitternacht in den prefs secretary_journal[_local]: random_window_start/_end, fehlend → 07:00–22:00). Der Scheduler (TemplateAlarmScheduler) liest das Fenster bei jedem arm()/deferRandom() aus den Einstellungen (SecretaryJournalApp.instance.repository.randomWindow()), behält die deterministischen Slots (Seed uid+Tag+Slot) und die System-Anpassung (DND +30 min, nächster Wecker −30 min, DeviceTimePolicy) bei; der TemplateReceiver-DND-Deferral nutzt dasselbe Einstellungs-Fenster. Daraus folgt der Editor-Workflow: normale Einträge = nur fixe Zeit (wie gehabt), Vorlagen = Fest/Zufällig-Umschalter; im Zufallsmodus wählt man nur noch die Anzahl pro Tag (Stepper), das Zeitfenster steuert man global in den Einstellungen — die Wiederholung (RRULE, bestimmt die Vorkommens-Tage) bleibt als zusätzliche Option. RandomPeriod, die Fenster-Pills, pro-Tag/pro-Woche-Chips und der Geräte-Hinweis im gemeinsamen Block sind entfernt (OccurrenceStrings). RandomSchedule.decode akzeptiert weiterhin das alte HHmm-HHmm:N:day|week-v61-Format (Fenster/Periode werden ignoriert, Schema-9- Exporte bleiben lesbar). DE/EN-Strings: occ_count_label („Anzahl pro Tag"), neu settings_section_random/settings_random_hint/settings_random_from/ settings_random_to/settings_random_default; gelöscht occ_range_label/ occ_period_day/occ_period_week/occ_device_hint. versionCode 62 == versionName 62 (local: 62-lokal).

Status 2026-09-11 (61)

Secretary Journal 61 (versionCode 61): Gemeinsamer Zeitpunkt-/Wiederholungs- Block mit Zufalls-Erinnerungszeiten (proof of concept, auf secretary-common-android v0.23.0). Der Editor nutzt jetzt für alle Eintragstypen das neue gemeinsame Composable DateTimeOccurrenceFields (common ui/): Datum-Pill (nativer DatePicker) und für gewöhnliche Einträge nur fixe Uhrzeit (TimePicker) — normale Einträge bleiben wie gewünscht rein FIXED. Vorlagen haben zusätzlich einen Umschalter „Fest / Zufällig": Im Zufallsmodus wählt man ein Zeitfenster (Von/Bis-Zeitpicks), eine Anzahl X pro Tag oder pro Woche und optional weiterhin die Wiederholung (RRULE, bestimmt die Vorkommens-Tage). Persistiert wird der Zufalls-Plan als VJOURNAL-Kategorie rand:<HHmm>-<HHmm>:<X>:<day|week> (RandomSchedule, JSON-Schlüssel randomSchedule, Export-Schema 9). Der TemplateAlarmScheduler bewaffnet je Vorlage mehrere exakte Alarme (Slot-Request-Codes 100+): je Tag/Woche werden X deterministisch gestreute Zeiten in das Fenster gelegt (Seed = uid + Tag + Slot, dadurch beim Re-Arm reproduzierbar). System-Anpassung (DND + Schlaf): DeviceTimePolicy (common) erkennt den aktuell aktiven Nicht-stören-Modus (NotificationManager.getCurrentInterruptionFilter) und die nächste Weckerzeit (Settings.System.NEXT_ALARM_FORMATTED; es gibt keine öffentliche Schlafenszeit-API — Digital-Wellbeing-Bedtime ist intern, der Wecker dient als Aufwach-Anker). Das Zufallsfenster wird gegen jetzt, aktive DND (+30 min Sicherheitsabstand) und den nächsten Wecker (−30 min) beschnitten. Fällt ein Zufalls-Alarm aus, während DND aktiv ist, deferiert der TemplateReceiver ihn auf einen späteren Zufalls-Slot desselben Tages (begrenzt auf 8 Wiederholungen, danach wird trotzdem benachrichtigt). Vorlagen-Speichern erlaubt RRULE oder Zufallsplan (bisher musste eine RRULE gesetzt sein); neue DE/EN-Strings occ_*. versionCode 61 == versionName 61 (local: 61-lokal).

Status 2026-09-11 (60)

Secretary Journal 60 (versionCode 60): Tägliche Erinnerung entfernt (kann über Vorlagen abgebildet werden). Der Abschnitt „Benachrichtigungen" in beiden Einstellungen-Screens (Toggle „Tägliche Erinnerung" + Erinnerungszeit-Zeitpicker) ist entfernt; dahinter liegt der komplette journal-Erinnerungs-Stack: JournalNotificationScheduler/ JournalReminderReceiver gelöscht, der Manifest-Receiver entfernt, scheduleAll-Aufrufe aus beiden MainActivities/BootReceivers entfernt, die Prefs-Methoden (notificationsEnabled/saveNotificationsEnabled/ reminderHour/reminderMinute/saveReminderTime in beiden Repositorys) und die DE/EN-Strings notif_channel_journal/notif_title/notif_text/ settings_section_notifications/settings_daily_reminder/ settings_daily_reminder_sub/settings_reminder_time gelöscht. openAppIntent (aus dem Journal-Scheduler) ist in den MedicineReminderScheduler umgezogen, den der Medikamenten-Receiver nutzt. Die „wann soll ich mich ans Tagebuch erinnern"-Funktion lässt sich jetzt über die Eintragsvorlagen (RRULE) inklusive Benachrichtigung abbilden. Medikamenten-Erinnerungen und Vorlagen-Alarme bleiben unberührt (POST_NOTIFICATIONS und SCHEDULE_EXACT_ALARM bleiben). versionCode 60 == versionName 60 (local: 60-lokal).

Status 2026-09-11 (59)

Secretary Journal 59 (versionCode 59): Proposals komplett entfernt (Gesammelte Listen + Vorschlags-Neuberechnung) + gemeinsame Einstellungs-Sektion angepasst. Der Screen „Gesammelte Listen" (Route gathered, GatheredScreen/GatheredStore) und der Collections-Änderungs- Screen (Route collections, CollectionsScreen/ JournalCollectionsContract) wurden komplett entfernt; die Routen, der Header-Button „Sammlungen" (onCollections/collectionsLabel in Carousel und Kalender, AppHeader) und die Navigation entfallen. Beide ViewModels verlieren den gesamten Vorschlags-Zustand (proposalSet, gathered-Listen, maybeRecalcProposals u. w.) und die Collections-Verwaltung (CRUD, Selektion, collectionBusy, pendingCollectionIds/recomputePending); drei Todos um Medikament/Vorlagen etc. bleiben. ProposalEngine ist auf die Trigger/Skill- Korrelation (Editor) verschlankt; ProposalRecalcScheduler/ ProposalRecalcReceiver gelöscht, der Manifest-Receiver und der Settings-Abschnitt „Vorschläge" (Zeitpicker + „Gesammelte Listen verwalten"-Button) in beiden Settings-Screens entfernt. Die gemeinsame SecretarySettingsScreen (common) bekommt die Option showContextMenuSettings (Default true, Journal übergibt false), sodass die „Eintrags-Kontextmenü"-Einstellung je App unterdrückbar ist. Beim Start (SecretaryJournalApp.onCreate) wird die alte Prefs secretary_journal_gathered geleert. Entfernte DE/EN-Strings: gathered_*, settings_section_proposals, settings_proposals_hint, settings_recalc_time, settings_manage_gathered, collections_subtitle, coll_*, vm_journal_create_failed, vm_journal_rename_failed, vm_journal_copy_failed, vm_friendly_delete. loadCollections()/loadEntriesInternal(collection)/ moveEntry bleiben (Einträge hängen weiter an der Journal-Collection). versionCode 59 == versionName 59 (local: 59-lokal).

Status 2026-09-10 (57)

Secretary Journal 57 (versionCode 57): Medikament nur mit Wirkstoff, keine Vorschlags-Chips mehr + vereinfachte Eintrags-/Vorlagen-Titel. Der Medikamenten-Editor hat nur noch das Feld „Wirkstoff": Das "Name"-Feld ist entfernt; beim Speichern wird medicineName (für Anzeige/Sammeln/Teilen) automatisch auf den Wirkstoff gesetzt, falls er leer blieb (Legacy-Einträge mit Name bleiben gelesen). Alle Vorschlags-Chips in den Editoren sind entfernt: Highlights (edit_proposals_historic), Medikament, Essen und Trigger/Skill (jeweils edit_already) – die AssistChip-Zeilen fallen weg. In beiden ViewModels sind die dafür ungenutzten Getter (proposals, triggerProposals, skillProposals, foodProposals, medicineProposals, skillRecommendations) und das ungenutzte updateMedicineName entfernt; die tägliche Vorschlags- Neuberechnung-Infrastruktur bleibt bestehen. Eintragslisten-Titel verschlankt: Medikament zeigt nur den Wirkstoff (ohne Dosis), Getränk nur den Namen (ohne Menge/ml), Essen nur die Art (Mahlzeit/Snack, ohne Text und kJ); Highlights zeigen weiterhin nur den Highlight-Text. Vorlagen-Zeilen zeigen in der zweiten Zeile das nächste Auftreten („Nächstes Mal: dd.MM.yyyy, HH:mm", berechnet via TemplateAlarmScheduler.nextOccurrence) statt des RRULE-Labels (neuer String template_next); ohne RRULE bleibt das „Vorlage"-Badge. Die zugehörigen DE/EN-Strings (edit_proposals_historic, edit_already, edit_name_label, edit_name_placeholder) sind gelöscht. versionCode 57 == versionName 57 (local: 57-lokal).

Status 2026-09-10 (56)

Secretary Journal 56 (versionCode 56): Eintragsvorlagen (Templates) mit Accept/Reject-Benachrichtigung. Die Überschrift „Einträge" in der Hauptansicht (Karussell) ist jetzt tippbar und schaltet zwischen der Eintragsliste und einer Vorlagen-Liste um (SwapVert-Icon, leere Hinweis- Zeile, Badge erscheint). Der Typ des Extended-FAB wechselt mit („Neue Vorlage"); Vorlagen sind alle bekannten Eintragstypen über das isTemplate-Flag auf JournalEntry (im VJOURNAL als Kategorie is:template, im JSON-Export Schema 8 als isTemplate), gespeichert wird die Wiederholung als RRULE (rrule:<rule>-Kategorie), der Editor zeigt dafür eine neue Sektion „Wiederholung" (FilterChip „Keine"/Wiederholung über den gemeinsamen RecurrenceDialog). Vorlagen lassen sich nur mit RRULE speichern (sonst template_requires_rrule-Fehler). TemplateAlarmScheduler bewaffnet für jede Vorlage einen exakten Alarm auf das nächste Auftreten (RFC-5545-Expander aus secretary-common-android) und legt in PendingTemplateQueue einen Snapshot ab; beim Auslösen zeigt TemplateReceiver eine High-Priority-Benachrichtigung mit Eintragen (Accept) und Überspringen (Reject): Accept klont den Snapshot in einen echten Eintrag (neu uid+href, isTemplate=false, rrule="", „Akzeptiert"-Zeit in occurredAt), legt ihn in der Accepted-Queue ab und armt die nächste Wiederholung neu; Reject verwirft nur und armt neu. Beide ViewModels (remote + local) drainen die Accepted-Queue beim Start, persistieren die Einträge (remote per CalDAV+Cache, local per JSON-Datei) und rufen rearmAll beim Start, Speichern/Löschen und nach Boot auf (beide BootReceiver/Manifest-Receiver registriert). Die Zeile einer Vorlage zeigt Titel + RRULE und einen Play-Button „Jetzt eintragen" (runTemplateNow speichert sofort einen echten Eintrag ohne RRULE). Die Eintragsliste nennt außerdem Stuhl/Urin jetzt explizit („Stuhl Typ X"/„Urin Stufe X") und die Eintragskarten sind kompakter (halbierte Höhe, einzeilig). DE/EN-Strings ergänzt. versionCode 56 == versionName 56 (local: 56-lokal).

Status 2026-09-10 (55)

Secretary Journal 55 (versionCode 55): Eintragswiederholung (Recurrence) komplett entfernt. Die per Eintrag setzbare RRULE-Wiederholung aus v49 ist kein Feature mehr: JournalEntry trägt kein rrule-Feld mehr, VJOURNAL- RRULE:-Kategorien werden beim Lesen ignoriert und beim Schreiben nicht mehr erzeugt (JournalTransfer bleibt Schema 7, Ex- und Importe älterer Schemata werden weiter gelesen, rrule wird verworfen). Entfernt wurden der Wiederholungs-Button samt RecurrenceDialog im Editor (updateRrule in beiden ViewModels), die Scheduler/Receiver-Dateien JournalRecurrenceScheduler/JournalRecurrenceReceiver, die PendingRecurrenceQueue (Accept/Reject-Benachrichtigung) samt Manifest-Receiver und Re-Arm-Aufrufen in MainActivity/BootReceiver, der Recurrence-Fade in entryOpacity sowie alle Recurrence-Strings (DE/EN). Damit entfällt, dass ein akzeptierter wiederkehrender Eintrag ohne Wiederholungsflag angelegt wurde und man zum Stoppen der Serie den Ursprungseintrag suchen musste. versionCode 55 == versionName 55 (local: 55-lokal). Zudem nennt die gemeinsame Einstellungs-Sektion in secretary-common-android den Langdruck-Kontextmenü-Block jetzt „Entry-Contextmenu".

Status 2026-09-10 (51)

Secretary Journal 51 (versionCode 51): Getränk in den Food-Typ integriert + nur Highlights einmal pro Tag. Der seit v50 eigenständige Eintragstyp „Getränk" wurde in den Typ „Essen" als dritte Unterart „Getränk" verschmolzen: EntryType.DRINK ist entfernt (EntryType-Reihenfolge TEXT/MOOD/EXCRETA/MEDICINE/FOOD/TRIGGER/SKILL); FoodFlavour hat neu DRINK("drink","Drink") und der Food-Editor zeigt neben Mahlzeit/Snack automatisch den dritten Chip „Getränk". Bei Drink-Flavour werden Getränkename + Menge in ml editiert (Vorschläge aus der Historie setzen den Namen, übernimmt updateDrinkName), sonst kJ + Text. Serialisierung: VJOURNAL bleibt SUMMARY=food, DESCRIPTION = Name bei Drink (einzeln verschlüsselbar), CATEGORIES=[food, food:drink, drinkml:<N>] (kein kj:); JournalTransfer ist auf Schema 7 gestellt und liest v50-Exporte mit entryType:"drink" als FOOD+DRINK (foodFlavour-Fallback, drinkName-Entschlüsselung statt foodText). FAB-/Typauswahl (Kalender + Karussell, EntryTypePrefs normalisiert legacy drink→food), Recurrence (Queue/Scheduler-Parse alter drink-Einträge, Receiver ohne DRINK, FOOD-Summary mit Drink-Name), Icons/Farben (entryIcon(entry) zeigt LocalDrink + Drink-Cyan für Drink-Flavour; Kacheln/Zeilen), Teilen-Text, syncGatheredFromEntries/ProposalEngine (Drink-Namen statt Food-Text in die Listen) und die Import-Zusammenführung beider ViewModels (FOOD kopiert jetzt auch drinkName/drinkAmountMl) sind angepasst. Nur noch Highlights (TEXT) sind einmal pro Tag (openTextEntryForDate weiter find-or-create); alle übrigen Typen sind mehrfach pro Tag und openMood/Excreta/Trigger/Skill/Medicine/FoodEntryForDate legen immer einen neuen Eintrag an. DE/EN-Strings: food_drink neu, edit_subtype_drink entfernt, edit_drink_*/type_drink bleiben. versionCode 51 == versionName 51 (local: 51-lokal).

Status 2026-09-10 (50)

Secretary Journal 50 (versionCode 50): Excreta-Typ (Stuhl/Urin) + eigener Getränke-Typ. Die Eintragstypen „Stuhlgang" und „Hydration" wurden zu einem Typ „Excreta" zusammengeführt (ein Editor mit Untertyp-Auswahl Stuhl/Urin, ExcretaKind; Speicher-Tags umbenannt: VJOURNAL SUMMARY=excreta, CATEGORIES excreta:stool + stool:<N> bzw. excreta:urine + urine:<N>). Beide Untertypen haben wie bisher eine Skala (Bristol 1-7 bzw. Armstrong/Urinfarbe 1-8, UrineType neu benannt statt HydrationType); beim Wechsel des Untertyps wird die andere Skala geleert; der Editor zeigt je Untertyp die richtige Skala im selben Maskenaufbau wie Essen. Alte Daten bleiben lesbar: EntryType.fromSummary mappt stool/hydration → EXCRETA, UrineType.fromCategories akzeptiert legacy hydration:<N>, JournalTransfer liest Schema-≤5-Exporte mit hydrationType-Fallback (Schema 6). Neu ist der Typ „Getränk": VJOURNAL SUMMARY=drink, DESCRIPTION = Name (einzeln verschlüsselbar), CATEGORIES=[drink, drinkml:<N>]; der Editor bietet optionales Namensfeld und Mengenfeld in ml. Neuanlage von Excreta/Drink ist mehrfach pro Tag möglich (openExcretaEntryForDate/openDrinkEntryForDate, immer neuer Eintrag); die Schnell-Dialoge für Stuhl/Hydration (Karussell + Kalender) und saveStoolEntry/saveHydrationEntry wurden entfernt. FAB-Namen, Icons/ Farben (Stuhlgrün/Urin-Cyan), Kalender-Kacheln, Teilen-Text, Recurrence-UI/-Receiver, EntryTypePrefs (Legacy-Normalisierung stool/hydration → excreta) und die Import-Zusammenführung beider ViewModels sind angepasst. versionCode 50 == versionName 50 (local: 50-lokal).

Status 2026-09-10 (48)

Secretary Journal 48 (versionCode 48): Sprachunterstützung (Deutsch/ Englisch). Alle hartcodierten deutschen UI-/ViewModel-Texte wurden in Android-String-Ressourcen ausgelagert: app/src/main/res/values/strings.xml (Deutsch, Standard) und app/src/main/res/values-en/strings.xml (Englisch). Ein neuer Abschnitt „Sprache" in beiden Einstellungen-Screens (remote + local, mit LocalePrefs + App-recreate) schaltet zwischen Deutsch und Englisch um; die App liest Texte über SecretaryJournalApp.instance .localizedContext(). Betroffen sind alle Screens (Login, Einstellungen, Kalender, Karussell, Editor, Statistik, Gesammelte Listen, Sammlungen, Verschlüsselung/Passwort/Biometrie, Export/Import, Entsperren), die Erinnerungs-Benachrichtigungen und sämtliche ViewModel-Meldungen (Fehler, friendly()-Fehler des Remote-Flavors, Export/Import-Rückmeldungen). Deutsche KDoc/Kommentare wurden ins Englische übersetzt. versionCode 48 == versionName 48 (local: 48-lokal).

Status 2026-09-10 (49)

Secretary Journal 49 (versionCode 49): Optionale Eintragswiederholung mit Accept/Reject-Benachrichtigung. Jeder Eintragstyp außer MOOD kann jetzt ein optionales RRULE (rrule-Feld) tragen – gespeichert als RRULE:<rule> in VJOURNAL CATEGORIES (Schema 5 in JournalTransfer). Wenn ein nicht-leeres rrule vorhanden ist, bewaffnet der JournalRecurrenceScheduler einen exakten Alarm für das nächste Auftreten (IEEE RFC 5545 über den gemeinsamen Recurrence-Expander); beim Auslösen zeigt JournalRecurrenceReceiver eine HIGH-Wichtigkeitsbenachrichtigung mit zwei Aktionen an:

Die vollständigen Einträge werden in SharedPreferences (secretary_journal_recurrence) als JSON gespeichert, sodass Alarme nach einem Neustart über JournalRecurrenceScheduler.rearmAll() wiederhergestellt werden; beide BootReceiver und MainActivity.onResume rufen rearmAll auf. Die ViewModelle beider Editionen (remote + local) waffen beim Speichern/Löschen via scheduleEntry/cancel, drainen PendingRecurrenceQueue bei App-Start, nach Entsperren und auf ACTION_ACCEPTED-Broadcasts (exakt wie PendingMedicineQueue).

Der Editor zeigt unter der Uhrzeit (nicht bei MOOD) die neue Sektion „Wiederholung" mit dem aktuellen Wert aus recurrenceLabel(); Tippen öffnet den bestehenden RecurrenceDialog aus secretary-common-android. updateRrule(rrule) in beiden ViewModels passt den Entwurf an. DE/EN- String-Ressourcen hinzugefügt. versionCode 49 == versionName 49 (local: 49-lokal).

Status 2026-09-10 (47)

Secretary Journal 47 (versionCode 47): Optionale Stimmung (zweiter Eintrag) und optionale Tendenz an allen Einträgen. Jeder Eintrag außer Stimmung kann optional ergänzt werden: Der Editor zeigt direkt unter dem Zeitpunkt-Abschnitt für alle nicht-Stimmungs-Typen (Highlights/Stuhl/ Hydration/Trigger/Skill) eine neue Sektion „Stimmung miterfassen (zweiter Eintrag)" – Auswahl „Keine" oder Smiley-Wert (Glücklich/Normal/Traurig, FilterChips mit Emoji). Beim Speichern legt ein gewählter Wert einen eigenen Stimmungs-Eintrag (MOOD) zusätzlich an (Same-Date, gleiche occurredAt-Zeit wie der Haupt-Eintrag; remote + local online wie offline, Abstract im eigenen saveMoodSecondEntryFor). Die Auswahl ist reine Anlege-Kuration: sie wird nie vorbelegt, löscht nie bestehende Stimmungs-Einträge (deselect = einfach nicht anlegen; ein vorhandener Stimmungs-Eintrag des Tages bleibt unberührt und ist über seinen eigenen Editor änder-/löschbar) und gilt nur für den nächsten Speichervorgang. Zusätzlich hat jeder nicht-Stimmungs-Typ eine optionale Tendenz (↗ Hoch / ↘ Runter / Keine, FilterChips mit Deselect). Für Trigger/Skill ersetzt die gemeinsame Sektion die bisherige Tendenz-Auswahl (jetzt auch abwählbar), für Highlights/Stuhl/Hydration ist sie neu. Die Tendenz wird wie bei Trigger/Skill als tendency:up|down-Kategorie im selben VJOURNAL gespeichert (und von JournalTransfer als tendency serialisiert – Schema 4 bleibt); fromNote liest sie jetzt auch für TEXT/STOOL/HYDRATION. Stimmungs-Einträge bleiben ohne Tendenz (wie ab v42). Der Teilen-Text des Kalenders hängt die Tendenz-Zeile generisch an jede Eintragsart an. versionCode 47 == versionName 47 (local: 47-lokal).

Status 2026-09-10 (46)

Secretary Journal 46 (versionCode 46): Armstrong-Hydrations-Skala als Eintragstyp + wählbarer Zeitpunkt für neue Einträge. 1. Neuer Eintragstyp „Hydration": protokolliert den Hydrationsgrad über die Armstrong-Skala (Urinfarbe, Stufe 1 „Sehr hell, fast klar" bis 8 „Braun"; HydrationType mit level, label, description, Default Stufe 4). Völlig analog zur Bristol-Stuhl-Skala: HydrationScaleDialog listet alle acht Stufen mit Farbkreis je Urinfarbe (hydrationLevelColor(level)) und Beschreibung; im FAB-Typauswahl-Sheet (EntryTypePickerSheet) wie im Kalender speichert die Auswahl einen Hydration-Eintrag direkt ohne Editor (saveHydrationEntry, remote + local, mit at:<millis>-Voreinstellung); im Editor zeigt HydrationEntryBody (Subtitle „HYDRATION") die gewählte Stufe und öffnet die Skala neu (updateHydrationType). Persistiert als VJOURNAL SUMMARY=hydration, CATEGORIES=hydration:<N>; JournalTransfer speichert hydrationType (optional, Schema 4 bleibt unverändert, alte Exporte parsen mit null). Kalender-Tageskacheln (Icon LocalDrink, Farbe „Hydration cyan" HydrationColor), Eintragsliste (entryTypeIcon/entryTitle/entryColor), Teilen-Text und die Import-Zusammenführung aller fünf Typen in beiden ViewModels verstehen den neuen Typ. 2. Datum & Uhrzeit bei neuen Einträgen: Der Editor zeigt oben den Abschnitt „Zeitpunkt" mit Datum- und Uhrzeit-Schaltfläche (native DatePickerDialog/TimePickerDialog, Uhrzeit im 24h-Format, dd.MM.yyyy/ HH:mm). Neue Entwürfe nutzen JournalEntry.defaultOccurredAtFor(date) statt fester Jetzt-Zeit: exakt jetzt bei heute, sonst der geöffnete Kalendertag zur aktuellen Uhrzeit; setEntryDateTime(millis) re-anchort date (Kalendertag) und occurredAt gemeinsam (z. B. Eintrag für gestern 22:15). Alle createNewXEntry-Funktionen (TEXT/MOOD/STOOL/HYDRATION/TRIGGER/ SKILL) beider ViewModels verwenden die Voreinstellung; der Stuhl- und der Hydrations-Schnellspeicher erben sie ebenfalls. versionCode 46 == versionName 46 (local: 46-lokal).

Status 2026-09-10 (45)

Secretary Journal 45 (versionCode 45): Bristol-Stuhl-Skala mit Bildern. Die Typauswahl (BristolStoolDialog) zeigt statt des farbigen Punkts je Typ das Abbild der Stuhlform aus der Wikipedia/Bristol-Stuhlformen-Skala (Bristol_stool_scale) auf einem hellen Chip (128 px breit, transparent). Die Einzel-Bilder bristol_1.png…bristol_7.png (app/src/main/res/drawable-nodpi/, 123×52, aus den Commons-Dateien BristoStool_1.png…BristoStool_7.png) stammen aus File:BristolStoolChart.png von Jmarchn und sind unter CC BY-SA 3.0 lizenziert. Beide Einstellungen-Screens (remote + local) tragen dafür einen neuen Abschnitt „Lizenz & Quellen" mit der Attribution (Autor, Quelle, Lizenz) und einem klickbaren „Lizenz ansehen (CC BY-SA 3.0)"-Link (öffnet creativecommons.org). Die Zuordnung BristoStool_1..7 → Typ 1..7 erfolgt im Dialog über BristolType.numericValue. versionCode 45 == versionName 45 (local: 45-lokal).

Status 2026-09-10 (44)

Secretary Journal 44 (versionCode 44): GET_ACCOUNTS für das zentrale Konto (remote). Die Remote-Edition deklariert jetzt android.permission.GET_ACCOUNTS (neben dem legacy READ_ACCOUNT). Das gemeinsame Sekretär-Konto (AccountManager, Typ org.beowulf.secretary) wird damit direkt lesbar und hängt nicht mehr ausschließlich an der Signer-Visibility-Provisionierung des Android-Kontos – ein Update der App konnte diese Provisionierung abwerfen, sodass AccountResolver.resolve() ein leeres Konto lieferte (Login-Screen, keine Daten, Passwort-Gedächtnis weg), während andere Sekretär-Apps (mit GET_ACCOUNTS) das Konto weiter nutzten. Server-Daten (VJOURNALs) bleiben unberührt. versionCode 44 == versionName 44 (local: 44-lokal).

Status 2026-09-10 (43)

Secretary Journal 43 (versionCode 43): Uhrzeit in allen Eintrags-Zeitpunkten. Der Editor zeigt in der Trigger/Skill-Korrelation („Auslöser der letzten 3 Tage", „Bewährte Gegenmittel"/„Risiko-Muster") jetzt je Zeile die exakte Uhrzeit des Eintrags (dd.MM., HH:mm) statt nur das Datum; ProposalEngine.TriggerSkillLink trägt dafür die genauen Log-Zeitpunkte (triggerOccurredAt/skillOccurredAt, null für alte datum-only-Einträge) und die Verkettung/Tendenz-Verordnung ordnet innerhalb eines Tages nach exakter Zeit (Fallback Mitternacht). Auch der Teilen-Text des Kalenders enthält die Uhrzeit (dd.MM.yyyy, HH:mm). Damit bleibt die Timeline auch bei mehreren Einträgen desselben Typs am selben Tag eindeutig. versionCode 43 == versionName 43 (local: 43-lokal).

Status 2026-09-09 (42)

Secretary Journal 42 (versionCode 42): Keine Tendenz mehr für Stimmung. Die Tendenz-Auswahl (↗/↘) wurde aus dem Stimmungs-Editor entfernt – ein Stimmungs-Eintrag ist nur noch eine Stimmung (wie ursprünglich in v37 zugeordnet); Stimmungs-Editor zeigt nur noch die Smiley-Auswahl. Bestehende Stimmungs-Einträge mit persistierter Tendenz bleiben lesbar, Trigger/Skill behalten ihre Tendenz. versionCode 42 == versionName 42 (local: 42-lokal).

Status 2026-09-09 (41)

Secretary Journal 41 (versionCode 41): Statistik-Screen für Trigger & Skills. Neue StatsEngine (lokal, rein; teilt sich mit ProposalEngine das „nie serverseitig"-Prinzip) berechnet aus der Eintrags-Historie: Trigger-Häufigkeit und Skill-Häufigkeit (je Text: Gesamtzahl plus Tendenz-Aufschlüsselung ↗/↘/neutral, sortiert nach Häufigkeit, Display auf Top-20 mit „+ n weitere") sowie den Tendenz-Verlauf: wochenweise (Montag-Start, WeekFields deutsch) kombinierte Trigger+Skill-Tendenz- Zählungen von der Woche des ältesten Tendenz-Eintrags bis zur aktuellen Woche. Beide ViewModels exponieren journalStats (reaktiver Getter). Neuer Screen StatsScreen (Route stats, erreichbar über den neuen Einstellungen-Button „Statistik ansehen" in einem eigenen Abschnitt „Statistik", remote + local): Bars über „Trigger-Häufigkeit"/„Skill-Häufigkeit" (mit ↗ n / ↘ n je Zeile) und eine Canvas-Balkengrafik des Tendenz-Verlaufs (grüne Balken = Hoch, rote = Runter, Skalierung auf das Maximum, Lücken = Wochen ohne Einträge) mit Datumsspanne und Legende darunter; Leerzustände, wenn noch nichts erfasst wurde. versionCode 41 == versionName 41 (local: 41-lokal).

Status 2026-09-09 (40)

Secretary Journal 40 (versionCode 40): Trigger/Skill-Evaluation im Editor. Beim Bearbeiten eines Skill- oder Trigger-Eintrags zeigt der Editor jetzt eine Tages-Korrelation zwischen Triggern und Skills mit farbigen Hinweisen. Die neue, live gerechnete Engine-Funktion ProposalEngine.correlateSkillAt(entries, date, skillTendency) verkettet alle Auslöser der letzten FOLLOWUP_WINDOW_DAYS (3 Tage inkl. heute) mit dem aktuell bearbeiteten Skill; correlateTriggerWithText(entries, text) liefert aus der Historie alle Skill-Vorkommen bis 3 Tage nach einem Trigger gleichen Texts (exakter Textmatch wie bei den Skill-Empfehlungen). Jede Kante (ProposalEngine.TriggerSkillLink) wird per correlationPattern(triggerTendency, skillTendency) klassifiziert: COUNTERMEASURE (Auslöser ↘ + Skill ↗ = bewährtes Gegenmittel, grün CorrelationGoodColor), DEGRADATION (Auslöser ↗ + Skill ↘ = Risiko-Muster/Belastungszeichen, orange CorrelationWarnColor) und NEUTRAL. Die ViewModels beider Editionen exponiieren editorCorrelation (getter, reaktive Sicht auf entries/editingEntry). Der Skill-Editor zeigt unter der Tendenz-Auswahl die „Auslöser der letzten 3 Tage" als Zeilen mit Tendenzpfeil, Datum und farbigem Hintergrund je Muster plus eine Insight-Zeile („Gegenmittel-Muster …"/„Risiko-Muster …"/Aufforderung zur Tendenz-Wahl); der Trigger-Editor zeigt „Bewährte Gegenmittel" (↗-Skills, n×) in Grün bzw. „Risiko-Muster" (↘-Skills) in Orange für den eingegebenen Text – bei leerem Text hilft der Hinweis, den Auslöser einzutragen. versionCode 40 == versionName 40 (local: 40-lokal).

Status 2026-09-09 (39)

Secretary Journal 39 (versionCode 39): FAB + ganztägige Eintragsliste + Uhrzeit je Eintrag + Tendenz für Stimmung + Verwaltung gesammelter Listen mit Rückwirkung. Die Hauptansicht (Karussell-Screen) bekommt ein Extended-FloatingActionButton „Neuer Eintrag", das die gemeinsame Typauswahl öffnet; Tippen auf den Smiley öffnet direkt den heutigen Stimmungs-Eintrag (Langpressen weiterhin Kalender). Stimmungs-Einträge haben jetzt wie Trigger/Skill eine manuelle Tendenz hoch/runter (TendencyCell-Auswahl im Editor; gespeichert als tendency:up|down-Kategorie und in JournalTransfer als tendency); die Hauptansicht zeigt die aktuelle Tendenz (letzter Stimmungs-Eintrag) als Badge unten rechts am Smiley plus die Zählung aller ↗/↘ über die gesamte Historie. Unter dem Smiley ersetzt eine vollständige Eintragsliste (neueste zuerst bis älteste) die bisherigen „nur-heute"-Karten: jede Zeile zeigt Typ-Icon/-Farbe, Text bzw. Smiley-Label, dd.MM.yyyy, HH:mm und den Tendenz-Pfeil, Tippen öffnet den Editor. Dafür trägt jeder JournalEntry ein occurredAt (device-time epoch millis, beim Anlegen gesetzt, beim Speichern ergänzt), persistiert als at:<millis>-Kategorie im VJOURNAL und als occurredAt in JournalTransfer (Schema 4; alte Einträge bleiben datum-only und sortieren nach Datum+uid). Für die Verwaltung der Vorschläge gibt es GatheredStore (kuratierte Listen je Highlights/Trigger/Skill, JSON in Prefs secretary_journal_gathered) und den neuen Screen „Gesammelte Listen" (Route gathered, erreichbar aus beiden Settings-Screens über „Gesammelte Listen verwalten"): pro Liste Anzeige (x-fach notiert, zuletzt am …), Hinzufügen ohne Eintrag, Umbenennen/Zusammenführen und Entfernen – Änderungen werden durch Rückwärts-Anpassung in allen historischen Einträgen umgesetzt (TEXT: goodOne/Two/Three, TRIGGER/SKILL: text; remote per pushAllEntries, local per persist()). ProposalEngine.compute bevorzugt die kuratierten Listen und fällt bei leeren Listen auf aus den Einträgen abgeleitete Vorschläge zurück; neue Eintragstexte werden beim Laden/Speichern automatisch in die Listen übernommen. versionCode 39 == versionName 39 (local: 39-lokal).

Status 2026-09-09 (38)

Secretary Journal 38 (versionCode 38): Trigger und Skill als neue Eintragstypen + Umbenennung „Gute Dinge" → „Highlights". Der Tagebucheintrag umfasst jetzt fünf Typen: Highlights (ehem. „Gute Dinge", drei Textfelder), Stimmung, Stuhlgang, Trigger (Freitext + Tendenz hoch/runter) und Skill (Freitext + Tendenz hoch/runter). Trigger/Skill sind eigene VJOURNALs: SUMMARY = trigger/skill, DESCRIPTION = freier Text (verschlüsselbar als einzelner Blob wie TEXT), CATEGORIES = [trigger|skill, tendency:up|down] (Tendency per Tendency.fromCategories() geparst; fromString() akzeptiert up/down auch in Kategorien ohne Tendenz-Tag als null). JournalTransfer Serialisiert text + tendency (JSON-Schema 3) und verschlüsselt TRIGGER/SKILL-Freitext wie TEXT-Blobs. ProposalEngine (lokal, nie serverseitig) berechnet Vorschläge: Highlight-Vorschläge aus gesammelten Highlights, Trigger/Skill-Vorschläge aus jüngsten Einträgen desselben Typs, Skill-Empfehlungen je Trigger (Korrelation: Skill-UP nach Trigger-DOWN und umgekehrt, Fenster 3 Tage). ProposalRecalcScheduler (AlarmManager) ruft täglich um konfigurierbare Uhrzeit ProposalRecalcReceiver auf, der den Timestamp speichert und den ACTION_RECALC_RESULT-Broadcast sendet; die VMs empfangen diesen und aktualisieren proposalSet. Settings-Screen zeigt jetzt einen Vorschlag-Neuberechnungs-Zeitpicker (zusätzlich zum Erinnerungszeitpicker). EntryTypePickerSheet ist jetzt ein gemeinsames Composable (shared ui/ package) mit allen fünf Optionen (Highlights / Stimmung / Trigger / Skill / Stuhlgang); die privaten Kopien in Calendar und Carousel wurden entfernt. JournalTypeUi.kt definiert gemeinsame Icon-/Farb-Helpers (TriggerIconColor, SkillIconColor, moodIcon, moodColor, entryTypeIcon, tendencyIcon, tendencyColor). Kalender-Tageskachel zeigt bis zu vier Typ-Icons (sortiert nach EntryType-Ordinal) für die fünf Typen. Karussell zeigt heutige Trigger/Skill-Sektionen unter dem Highlight-Block. Kein Backward-Compat-Workflow für alte drei-Felder-Einträge; v36/v37-Einträge的有效 text-entries were already reinterpreted in v37 via fromNote() fallback. versionCode 38 == versionName 38 (local: 38-lokal).

Status 2026-09-09 (37)

Secretary Journal 37 (versionCode 37): Drei Eintragstypen (remote + local). Der Tagebucheintrag ist jetzt ein TEXT-Eintrag (max. einer pro Tag) mit drei Textfeldern „Drei gute Dinge" (goodOne/goodTwo/ goodThree, als JSON im CalDAV-DESCRIPTION bzw. verschlüsselten Blob; JSON-Schema 2, Schema-1-Import wird ins Feld 1 migriert). Stimmung und Bristol-Stuhlgang wurden eigene Eintragstypen (Entwarnung: der bisher ungenutzte CalDAV-SUMMARY-Tag wird als Typ-Marker text/mood/stool verwendet; CATEGORIES tragen mood:<name> bzw. stool:<N>). Stimmung und Stuhlgang sind mehrfach pro Tag möglich und werden über das neue FAB-Bottom-Sheet (Gute Dinge / Stimmung / Stuhlgang) angelegt; Stuhlgang öffnet die Bristol-Stuhl-Skala-Dialog (BristolStoolDialog) und speichert direkt (ohne Editor). Das Karussell zeigt unter dem Donut die heutigen guten Dinge, der Kalender pro Kachel bis zu drei Typ-Icons. Der Editor ist typabhängig: drei Gute-Dinge-Felder mit Vorschlags-Chips aus allen gesammelten guten Dingen (nachträglich), Stimmungs-Smiley-Zellen oder Stuhltyp-Anzeige. Die Erinnerung in den Einstellungen adressiert nur noch den Text-Eintrag. System-Kalender-Spiegel komplett entfernt (privates Journal: keine READ/WRITE_CALENDAR-Berechtigung, kein Boot-Sync, JournalSystemSyncAdapter/JournalSystemScheduler gelöscht). versionCode 37 == versionName 37 (local: 37-lokal).

Status 2026-09-09 (36)

Secretary Journal 36 (versionCode 36): Sammlungsverwaltung mit Langdruck-Kontextmenü (remote; secretary-common-android v0.19.0). Neue CollectionsScreen (Route collections, Button „Sammlungen" im AppHeader von Karussell- und Kalender-Screen, nur in der Remote-Edition) zeigt alle Journal-Sammlungen als Karten mit Umbenennen / Kopieren / Löschen (CollectionContextMenu), FAB „Journal" zum Anlegen (CreateCollectionDialog) und PendingBadge bei offline-pending Änderungen. Neue JournalViewModel-Aktionen createJournalCollection/renameJournalCollection/copyJournalCollection/ deleteJournalCollection über den gemeinsamen CrudManager (Write-Behind-Queue, „<Name> (Kopie)" inkl. aller Einträge), dazu pendingCollectionIds (PendingSync.snapshotState) und collectionBusy-Guard (offline → Banner + friendly-Fehler). Die Einträge folgen jetzt der aktiv gewählten Sammlung (selectJournalCollection, persistiert über last_collection, Fallback: erste VJOURNAL-Sammlung) – Anlegen/Auswahl laden deren Einträge, das Verschieben-/Duplizieren des Eintrags-Kontextmenüs läuft gegen die aktive Sammlung. Die lokale Edition implementiert das gemeinsame JournalCollectionsContract leer (kein Internet/Konto) und zeigt den Sammlungs-Button nicht. versionCode 36 == versionName 36 (local: 36-lokal).

Status 2026-09-09 (35)

Secretary Journal 35 (versionCode 35): Rebuild auf secretary-common-android v0.18.0. Kein App-Code geändert; der APK enthält jetzt die 412-Auto-Recovery (bedingte PUTs mit veraltetem If-Match-ETag holen einmalig die aktuelle Server-ETag und wiederholen den Schreibvorgang statt des „Notiz wurde auf dem Server geaendert"-Fehlers). versionCode 35 == versionName 35 (local: 35-lokal).

Status 2026-09-08 (34)

Secretary Journal 34 (versionCode 34): Konfigurierbares Kontextmenü. Die Aktionen Teilen / Kopieren / Verschieben / Löschen des Langdruck-Menüs auf der Tageskachel lassen sich in den Einstellungen (gemeinsame Sektion „Langdruck-Kontextmenü" aus secretary-common-android v0.16.0) per Checkbox aktivieren/deaktivieren (UiPreferences, Default: alle aktiv). ItemContextMenu blendet deaktivierte Aktionen aus und sperrt das Menü komplett, wenn alle vier aus sind (dann verhält sich die Kachel wie eine gewöhnliche klickbare Karte). versionCode 34 == versionName 34 (local: 34-lokal).

Status 2026-09-08 (33)

Secretary Journal 33 (versionCode 33): Gemeinsames Kontextmenü im Kalender-Raster (remote + local). Tage mit Eintrag haben jetzt ein Langdruck-Kontextmenü (ItemContextMenu aus secretary-common-android v0.15.0) direkt auf der Kalender-Kachel: Bearbeiten, Teilen (Text via Share-Sheet), Kopieren (Duplikat in derselben Journal-Collection via CrudManager.copyItem/copyItemOffline – remote; lokale Edition legt einen zweiten lokalen Eintrag an), Verschieben… (MoveCollectionDialog bei mehreren Journal-Collections; CrudManager.moveItem/moveItemOffline – remote; lokale Edition ist no-op) und Löschen (ConfirmDeleteDialog). versionCode 33 == versionName 33 (local: 33-lokal).

Status 2026-09-07 (30)

Secretary Journal 30 (versionCode 30): Aufgeräumter Header ohne Status-Chip. Der moderne Haupt-Header (ModernAppHeader in secretary-common-android) zeigt keinen Online-Status-Chip mehr; die Aktionsleiste (Sync, Einstellungen) sitzt jetzt rechts oben direkt im Hero-Header. Alle Überschriften verwenden die neue Typewriter-Schrift Special Elite (gebündelt in secretary-common-android, res/font/special_elite.ttf, Apache 2.0). versionCode 30 == versionName 30 (local: 30-lokal).

Status 2026-09-07 (29)

Secretary Journal 29 (versionCode 29): Crash-fix: Biometrie-Aktivierung. Der BiometricPrompt erfordert bei nur-stark-biometrischen Prompts (setAllowedAuthenticators(BIOMETRIC_STRONG)) einen negativen Button (setNegativeButtonText); ohne ihn wirft PromptInfo.Builder.build() ein IllegalArgumentException: Negative text must be set and non-empty. Der biometricPromptInfo setzt nun „Abbrechen". versionCode 29 == versionName 29 (local: 29-lokal).

Status 2026-09-07 (28)

Secretary Journal 28 (versionCode 28): Crash-fix: Settings-Screen / Biometrie. Beide Flavor-MainActivities erweitern jetzt FragmentActivity (statt ComponentActivity), damit BiometricPrompt einen gültigen Activity findet. Ohne dies crashtete die App beim Öffnen der Einstellungen aufgrund eines requireNotNull in rememberBiometricPrompt. versionCode 28 == versionName 28 (local: 28-lokal).

Status 2026-09-07 (27)

Secretary Journal 27 (versionCode 27): Verschlüsselungs-Migration aller Einträge. Das Aktivieren eines Passworts verschlüsselt nun sofort alle vorhandenen Einträge (remote: pushAllEntries schreibt jede verschlüsselte Notiz an den Server + Cache; local: persist() speichert die gesamte Datei verschlüsselt). Das Entfernen eines Passworts entschlüsselt ebenfalls alle Einträge (remote: pushAllEntries schreibt Klartext zurück an Server + Cache; local: persist() speichert Klartext). Außerdem: Biometrie-Prompt bindet den authentifizierten Cipher (kein frischer Cipher in onSuccess); MaterialTheme.colorScheme statt Colors. versionCode 27 == versionName 27 (local: 27-lokal).

Status 2026-09-07 (26)

Secretary Journal 26 (versionCode 26): Zwei Flavor + Verschlüsselung + Export/Import. Das Project baut über Gradle Product Flavors eine remote-Edition (org.beowulf.secretary.journal, sync/account/system-calendar) und eine local-Edition (org.beowulf.secretary.journal.local, rein on-device, kein Internet/Konto, JSON-Datei journal_local.json). Flavor-eigener Code liegt doppelt unter app/src/{remote,local}/java/…, geteilter Code in app/src/main/. Textverschlüsselung (JournalCipher): AES-256-GCM-Master-Key, per PBKDF2-HmacSHA256-Passwort (210k) und optionalem Android-Keystore-Biometrie-Wrap (BiometricPrompt) geschützt; bei aktiver Verschlüsselung werden Texte als sj1:-Blobs gespeichert (auch serverseitig; Systemkalender-Spiegel zeigt dann nur Stimmung/Datum, kein Text). Gesperrt erscheint statt der Navigation der UnlockScreen (Biometrie/PW). Export/Import als JSON über den System-Dateidialog (SAF), verschlüsselt bei aktiver Verschlüsselung, Import mischt nach Datum. das Buildsystem baut beide APKs (secretary-journal-26.apk + secretary-journal-local-26.apk). versionCode 26 == versionName 26 (local: 26-lokal).

Status 2026-09-07 (25)

Secretary Journal 25 (versionCode 25): System-Kalender-Spiegel. Jeder Journal-Eintrag erscheint als ganztägiges Ereignis (Titel <Stimmung> · <Datum>, Text im Beschreibungsfeld) im Android-Kalender – im geschützten Spiegel-Kalender secretary-journal (Constants in SystemCalendarMirror, nicht löschbar durch den Aufgaben-Spiegel bzw. das Spiegel-Modul der Kalender-App). Auslöser: App-Start/onResume, Login, Laden/Refresh, jede Änderung/Offline-Sync, Boot und der Button „Jetzt in System-Kalender synchronisieren" in den Einstellungen (Abschnitt „Systemkalender"). Dafür wird die Kalender-Berechtigung einmalig angefragt (READ/WRITE_CALENDAR, JournalSystemSyncAdapter/JournalSystemScheduler). versionCode 25 == versionName 25.

Status 2026-09-07 (24)

Secretary Journal 24 (versionCode 24): Hauptansicht aufgeräumt. Die textlichen Prozentangaben unter dem Donut-Smiley und die Hilfszeile „Tippen: neuer Eintrag · Halten: Kalender" wurden entfernt. Übrig bleiben Donut-Chart, der Smiley des letzten Eintrags und der (Optionale) Offline-Hinweis. versionCode 24 == versionName 24.

Status 2026-09-07 (23)

Secretary Journal 23 (versionCode 23): Einzel-Smiley mit Donut-Chart, konfigurierbares Auswertungsfenster. Die Hauptansicht zeigt nicht mehr drei überlagerte Smileys, sondern den Smiley des zuletzt erstellten Eintrags; um ihn herum zeichnet ein Donut-Chart (Canvas, MoodDonut) die Anteile Glücklich/Normal/Traurig im Auswertungsfenster. Das Fenster ist in den Einstellungen (Abschnitt „Auswertung") als Tage-Intervall (7/14/30/90/365T) wählbar, Standard 30 Tage (evaluation_window_days, JournalRepository). Der ViewModel berechnet moodPercentages/averageMood/latestMood über das konfigurierte Fenster. versionCode 23 == versionName 23.

Status 2026-09-02 (22)

Secretary Journal 22 (versionCode 22): Nur noch „Karussell"-Theme. Alle klassischen/MODERN-Zweige entfernt, UiStyle (secretary-common-android) auf das einzelne CAROUSEL-Enum reduziert. Klassische Screen-Varianten (Login, Einstellungen, Editor, Kalender, Hauptansicht), der Stil-Umschalter in den Einstellungen sowie alle uiStyle-Parameter entfernt. Die App verwendet durchgehend das moderne Editorial-Ledger-Design. versionCode 22 == versionName 22.

Status 2026-09-02 (21)

Secretary Journal 21 (versionCode 21): Smiley zentriert, Kalender als eigener Screen. Das Stimmungs-Composite-Smiley ist jetzt vertikal zentriert (weighted Spacer above/below). Long-Tap navigiert zum eigenen Kalender-Screen (Routes.CAROUSEL → Routes.CALENDAR), statt den Kalender inline ein-/auszublenden. Die Hilfszeile zeigt nur noch „Tippen: neuer Eintrag · Halten: Kalender". versionCode 21 == versionName 21.

Status 2026-09-02 (20)

Secretary Journal 20 (versionCode 20): Smiley-Tap Aktion, Kalender versteckt. FAB-Button komplett entfernt; Tippen auf das große Stimmungs-Composite (240dp, Icons 144dp) erstellt direkt einen neuen Eintrag für heute. Halten (Long-Tap) zeigt/versteckt den Monatskalender unterhalb. Die untere Hilfszeile informiert über die verfügbaren Aktionen. versionCode 20 == versionName 20.

Status 2026-09-02 (19)

Secretary Journal 19 (versionCode 19): Karussell entfernt – Stimmungs-Overlay mit Kalender. Der alte HorizontalPager-Karussell wurde komplett entfernt. Die „Karussell"-Ansicht zeigt jetzt ein 160dp-Composite-Smiley in der oberen Hälfte: drei gestapelte Material-Icons (MoodBad/SentimentNeutral/Mood) überlagern sich mit je einer Opazität proportional zum prozentualen Anteil der jeweiligen Stimmung der letzten 30 Tage. Darunter Prozentangaben pro Emoji, in der unteren Hälfte der volle Monatskalender mit Monatsnavigation. moodPercentagesLast30Days im ViewModel liefert die Stimmungsverteilung. versionCode 19 == versionName 19.

Status 2026-09-01 (16)

Secretary Journal 16 (versionCode 16): Einheitlicher Moderner Header – alle secretary-Apps teilen jetzt denselben modernen Haupt-Header (ModernAppHeader in secretary-common-android): Hero mit Monogramm + Status-Chip und darunter die identische Aktionsleiste (Sync, Einstellungen). Die Journal-Hauptansicht hat damit wieder wie im klassischen Design Sync- und Einstellungen-Buttons im Kopfbereich; der verdoppelte zweite Header (kleiner Screen-Header oder Einträge + Hero) wurde entfernt. versionCode 16 == versionName 16.

Status 2026-09-01 (15)

Secretary Journal 15 (versionCode 15): Komplett modernisierte Oberfläche (Moderner Stil). Kalender-Monatsansicht, Eintrags-Editor und Einstellungen haben jetzt einen vollständigen „Moderner Stil"-Zweig nach dem gemeinsamen Editorial-Ledger-Design (secretary-common-android): Serifen-Display-Typo, Pill-artige Karten, Hero-Header mit Monogramm, Status-Chips, Monats-Navigation mit tonalen Pfeilen, Stimmungs-Auswahl, moderne Leerszustände; der klassische Stil bleibt unverändert erhalten. Umschaltung über den globalen Schalter „Moderner Stil"; das Theme liefert im modernen Modus die secretaryModernTypography. versionCode 15 == versionName 15.

Status 2026-08-29 (12)

Secretary Journal 12 (versionCode 12): Sync-Fortschritt: kein Endlos-Spinner mehr nach Abschluss/Fehler – Fix im gemeinsamen SyncProgressUi (secretary-common-android): sobald ein Sync-Job beendet ist (DONE/FAILED), wird der Spinner/Progressbar nicht mehr gezeichnet – es erscheint nur noch der einmalige Toast. Vorher blieb der Status gesetzt und die Inline-SyncProgressUi zeigte bei beendetem/fehlgeschlagenem Sync dauerhaft einen Spinner bei 0/0. Server-Init-Sync läuft jetzt gegen den aktualisierten secretary-server 0.10.0 mit den /sync/*-Endpunkten. versionCode 12 == versionName.

Status 2026-08-29 (11)

Secretary Journal 11 (versionCode 11): Server-gesteuerter Sync mit Fortschritt – über den gemeinsamen SyncJobClient (secretary-common-android, POST /sync/start + GET /sync/status/{id}) startet JournalViewModel.runServerSync() beim manuellen Refresh (loadCollections/refresh) für jedes Journal-Collection einen Server-Sync-Job und pollt den Fortschritt. JournalCalendarScreen zeigt über das gemeinsame SyncProgressUi während des Syncs einen Spinner + Determinat-Progressbar (processed / total) und einmalig einen Toast („Sync abgeschlossen" / „fehlgeschlagen"). versionCode 11 == versionName.

Roadmap (Kurz)