Tray-Meldungen verschwinden - daher ein dauerhaftes Protokoll.
- Logger: threadsicheres Datei-Log in %AppData%\StarfaceOutlookSync\sync.log
mit Rotation bei 2 MB.
- MainForm protokolliert Sync-Start, Ergebnis, Konflikte (lokal + von anderen
Arbeitsplaetzen), Fehler und uebersprungene Laeufe (Sperre).
- Neuer Button "Protokoll" oeffnet LogViewerForm (Aktualisieren/Leeren/Ordner
oeffnen, scrollt ans Ende).
- README/CHANGELOG aktualisiert.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bisher bekam jeder Arbeitsplatz, der den Konflikt-Kontakt im Adressbuch hat,
den Hinweis - auch wenn er den Wert gar nicht selbst gepflegt hat.
Jetzt zeigt ein Client eine fremde Konflikt-Notiz nur, wenn er den Kontakt hat
UND sein eigener Feldwert vom uebernommenen (Gewinner-)Wert abweicht. Die
Pruefung laeuft VOR dem Sync (gegen den eigenen Mapping-Snapshot), bevor der
Sync den Stand auf den Gewinner-Wert angleicht.
- FieldConflict/ConflictNotice: stabiler FieldKey zusaetzlich zum Anzeige-Label.
- ContactMerger: GetValue/ValuesEqual per FieldKey (telefon-normalisiert).
- ConflictNotifier.GetPending: Filter "eigener Wert != Gewinner-Wert", bekommt
StarfaceId -> eigener Kontaktstand.
- MainForm zeigt die Hinweise jetzt vor dem Sync und liefert den eigenen Stand
aus den Mapping-Snapshots.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Wird ein echter Feld-Konflikt aufgeloest, erfahren jetzt auch die ANDEREN
Arbeitsplaetze davon - nicht nur der aufloesende Client.
- ConflictNotice-Modell + ConflictNotifier: schreibt pro Konflikt eine Notiz
in <shared>/conflicts/ (nach StarfaceId), liest beim Sync ungesehene Notizen
zu eigenen Kontakten, zeigt sie als Tray-Hinweis und merkt sich gezeigte
lokal (seen-conflicts.json). Veraltete Notizen (>7 Tage) werden aufgeraeumt.
- MainForm: schreibt nach einem Sync mit Konflikten die Notizen und zeigt
ausstehende Notizen anderer Clients (gefiltert auf eigene gemappte
StarfaceIds). AcquireCrossClientLock nimmt jetzt das gemeinsame Verzeichnis
als Parameter.
- README/CHANGELOG aktualisiert.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Verhindert, dass mehrere Arbeitsplaetze gleichzeitig dasselbe Starface-
Adressbuch synchronisieren (Dubletten/Lost-Updates bei echter Ueberlappung).
- Neues optionales Setting "Gemeinsames Verzeichnis" (UserSettings.SharedDirectory)
in der Einstellungen-Maske inkl. Ordner-Browser.
- SyncLock: atomare Lock-Datei (FileMode.CreateNew) im gemeinsamen Verzeichnis,
waehrend des Syncs offen gehalten -> bei Absturz gibt das OS das Handle frei
und ein anderer Client uebernimmt die verwaiste Datei (Stale-Erkennung 15 Min,
Loeschen scheitert am offenen Handle eines lebenden Halters).
- MainForm wartet vor dem Sync bis zu 2 Min auf eine freie Sperre, sonst wird
der Lauf uebersprungen. Ohne/bei nicht erreichbarem Verzeichnis laeuft der
Sync ohne diese Sperre weiter (lokaler Interlocked-Schutz bleibt).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bisher wurde bei einem Konflikt (beide Seiten geaendert) der ganze Datensatz
ueberschrieben - eine gleichzeitige Aenderung an einem anderen Feld ging
verloren (z.B. A aendert Telefon in Outlook, B aendert Mail in Starface ->
eine Aenderung weg).
Jetzt:
- Mapping speichert je Seite einen Snapshot des letzten Sync-Stands
(LastOutlook/LastStarface), zusaetzlich zu den Hashes.
- Bei beidseitiger Aenderung im Both-Modus wird feldweise gemergt
(ContactMerger): unterschiedliche Felder bleiben beide erhalten, nur bei
echtem Konflikt am selben Feld gewinnt Outlook.
- Echte Feld-Konflikte landen in SyncResult.Conflicts und werden im MainForm
per Tray-Meldung angezeigt.
- Snapshots werden in allen Baseline-Punkten gesetzt (Phase 1-3) und fuer
aeltere Mappings beim naechsten unveraenderten Sync nachgetragen.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Der Schutz gegen gleichzeitige Syncs (manuell vs. Auto-Sync-Timer) war ein
nicht-atomares pruefen-und-setzen auf einem volatile bool. Zwischen Pruefung
und Setzen konnten ein UI-Klick und der Timer-Thread beide durchrutschen und
zwei Syncs gleichzeitig starten.
Jetzt per Interlocked.CompareExchange atomar.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Outlook->Starface macht das Starface-Adressbuch zur exakten Kopie von
Outlook: Kontakte, die nur in Starface existieren, werden geloescht.
Starface->Outlook entsprechend umgekehrt (Phase 4).
Sicherheit:
- Loeschphase laeuft nur bei vollstaendig geladener Liste (unvollstaendige
Ladevorgaenge brechen schon vorher ab).
- Ist die Quelle komplett leer (z.B. falscher Ordner), wird die Loeschphase
uebersprungen statt die Zielseite zu leeren.
UI: Profil-Editor zeigt jetzt unter der Sync-Richtung einen Warnhinweis, der
das jeweilige Verhalten erklaert. README/CHANGELOG aktualisiert.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Im Both-Modus wurde ein auf einer Seite geloeschter Kontakt bisher auf der
anderen Seite einfach wieder angelegt, statt die Loeschung zu spiegeln.
Jetzt wird anhand der gespeicherten Baseline (LastOutlookHash /
LastStarfaceHash) entschieden:
- Gegenseite seit letztem Sync unveraendert -> es war eine Loeschung ->
auf der anderen Seite ebenfalls loeschen.
- Gegenseite wurde geaendert -> Bearbeitung gewinnt -> neu anlegen
(kein Datenverlust).
In den Ein-Richtungs-Modi bleibt die Quelle fuehrend: eine Loeschung im
Ziel wird aus der Quelle wiederhergestellt (StarfaceToOutlook legt einen
in Outlook geloeschten Kontakt jetzt ebenfalls wieder an statt ein totes
Mapping zu behalten).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Der vorherige Fix war zu konservativ: bei einem in der geladenen Liste
fehlenden Starface-Kontakt wurde das Mapping immer behalten und nichts neu
angelegt - auch wenn der Kontakt in Starface wirklich geloescht war. In
Richtung Outlook->Starface wurden geloeschte Kontakte dadurch nie wieder
angelegt.
Jetzt wird der Kontakt per ID abgefragt:
- existiert noch (anderes Adressbuch) -> Mapping behalten, nichts anlegen
- 404 (wirklich geloescht) -> in Both/OutlookToStarface neu anlegen
(Phase 2), in StarfaceToOutlook Loeschung nach Outlook spiegeln
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Behebt Dubletten auf beiden Seiten und sehr langsame Syncs:
- Getrennte Hash-Baselines pro Seite (LastOutlookHash/LastStarfaceHash)
statt eines gemeinsamen Hashes. Outlook und Starface stellen denselben
Kontakt unterschiedlich dar, wodurch der gemeinsame Hash nie passte und
bei jedem Lauf praktisch jeder Kontakt neu geschrieben wurde.
- Update-Methoden geben den frisch eingelesenen Stand zurueck, damit die
Baseline nach dem Schreiben korrekt gesetzt wird (sauberes Konvergieren).
- Unvollstaendig geladene Starface-Liste bricht jetzt mit Fehler ab
(inkl. Retry) statt still mit Teil-Liste weiterzuarbeiten - das liess
Kontakte faelschlich als geloescht erscheinen und erzeugte Dubletten.
- Fehlender Starface-Kontakt (anderes Adressbuch) behaelt das Mapping,
statt es zu verwerfen und neu anzulegen.
- Lockereres Re-Matching: gleicher E-Mail- oder voller Namens-Treffer
reicht; umformatierte Telefonnummern blockieren ihn nicht mehr.
- Starface-Kontaktdetails werden parallel geladen (8 gleichzeitig).
Bestehende Mappings werden beim ersten Sync automatisch migriert.
CHANGELOG.md hinzugefuegt.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>