Merge branch 'main' into dev/jappel
Reconciles two independent lines of work: main cherry-picked and then extended dev/jappel's build-script/config-portability/rename-tab/ COM-port fixes, additionally fixing a config-loss bug (rebuild wiped the config when it lived in the install dir -- moved to roaming %APPDATA% instead) and adding free-text notes per action plus a frameless resizable window. dev/jappel keeps its .mcp.json registration and docs/ reference tree, which main deliberately left out. Conflict resolutions favored main's versions where the two sides solved the same problem (config location, build deploy target, COM-port release, tab rename) since main's fixes were validated against a real rebuild-wipes-config incident. docs/architecture.md and docs/data-model.md updated to describe the resulting %APPDATA% config path and the note field.
This commit is contained in:
commit
189ec01e68
11 changed files with 470 additions and 125 deletions
96
AGENTS.md
96
AGENTS.md
|
|
@ -93,9 +93,8 @@ Nutzerorientierte Einführung: [`README.md`](README.md).
|
|||
Fehler hier live aufgedeckt.
|
||||
|
||||
Vollständige Modulübersicht mit Zeilenreferenzen bei Bedarf direkt im Code
|
||||
nachschlagen — die Dateien sind klein genug, dass eine separate
|
||||
`docs/current-architecture.md` hier keinen Mehrwert hätte (siehe
|
||||
Dokumentation und Verifikation unten für die Größeneinschätzung).
|
||||
nachschlagen. Menschenlesbare Referenzdoku (Architektur, Datenmodell,
|
||||
Protokoll) liegt in `docs/`, siehe „Dokumentation und Verifikation" unten.
|
||||
|
||||
## Kritische Domänenregeln
|
||||
|
||||
|
|
@ -114,6 +113,18 @@ Dokumentation und Verifikation unten für die Größeneinschätzung).
|
|||
(`profile_names`) — die Firmware-Structs haben keinen Platz für einen
|
||||
String (Header exakt 32B, jedes Profil exakt 236B, alles verplant). Sie
|
||||
landen nie aufs Board, egal welcher Schreibpfad benutzt wird.
|
||||
- **Notizen** (freier Text je Button/Encoder-Aktion, seit 2026-08-15) sind
|
||||
aus demselben Grund rein lokal: leben im `"note"`-Feld JEDER Action
|
||||
(`{"type","data","note"}`), nicht in einer separaten Struktur. `to_binary`/
|
||||
`pack_config` ignorieren das Feld beim Schreiben (liest nur type/data),
|
||||
`from_binary` liefert frisch vom Board immer `note=""` (Board kennt keine
|
||||
Notizen) — `versapad_combined.merge_notes(neu, alt)` kopiert bestehende
|
||||
Notizen nach jedem `load_from_board()`/`fetch_from_board()` zurück, sonst
|
||||
gingen sie bei jedem Board-Refresh verloren. Action-Typ wechseln
|
||||
(`set_button_key` etc.) darf die Notiz NICHT loeschen (baut die neue
|
||||
Action ueber `_replace_action()`/`dlg.action["note"]` mit der alten Notiz),
|
||||
nur `set_button_note()`/`set_encoder_note()`/das Notiz-Feld im
|
||||
Programmiermodus-Dialog aendern sie gezielt.
|
||||
- Der COM-Port ist exklusiv. Live-Sync und Programmiermodus schalten sich
|
||||
gegenseitig aus (ein `VersaPadLink` kann nicht von zwei Konsumenten
|
||||
gleichzeitig genutzt werden); VersaGUI läuft als Tray-App dauerhaft im
|
||||
|
|
@ -126,6 +137,28 @@ Dokumentation und Verifikation unten für die Größeneinschätzung).
|
|||
vorhanden, und fällt sonst auf die klassischen `versapad_config{1,2,3}.json`
|
||||
zurück — beide Ansichten müssen dieselbe Quelle zeigen, sonst wirkt eine
|
||||
Bearbeitung "verschwunden".
|
||||
- **Config-Pfad darf NIE im Installationsverzeichnis liegen (2026-08-15,
|
||||
Datenverlust-Bug):** `build_and_deploy.ps1` räumt sein Zielverzeichnis vor
|
||||
jedem Deploy komplett ab (`Remove-Item $localDir -Recurse -Force`). Nachdem
|
||||
`app_dir()` am selben Tag auf genau dieses Verzeichnis gezeigt hatte, hat
|
||||
**jeder Rebuild die Nutzer-Config mitgelöscht**; die App hat sie danach
|
||||
kommentarlos leer vom Board neu aufgebaut (`load_or_fetch()` →
|
||||
`fetch_from_board()`), wodurch alle Notizen weg waren. Besonders tückisch:
|
||||
Board-Bindings und LEDs sahen danach völlig normal aus, nur die rein
|
||||
lokalen Felder (Notizen, Profilnamen) fehlten -- der Schaden ist also
|
||||
unsichtbar, wenn man nur aufs Grid schaut. Fix: `app_dir()` liefert jetzt
|
||||
`%APPDATA%\VersaPadViewer` (Roaming), getrennt vom Installationsordner in
|
||||
`%LOCALAPPDATA%`; zusätzlich rettet `build_and_deploy.ps1` vorgefundene
|
||||
`versapad_config*.json` aus dem Zielverzeichnis über den Deploy hinweg
|
||||
(für Altinstallationen). **Regel für künftige Änderungen: Programm- und
|
||||
Datenverzeichnis nie zusammenlegen, egal wie praktisch "alles an einem
|
||||
Ort" klingt.**
|
||||
- **Nur EIN Config-Pfad, unabhängig vom Startweg (2026-08-15):** `app_dir()`
|
||||
hat bewusst KEINEN `sys.frozen`-Zweig mehr. Vorher sah die gebaute `.exe`
|
||||
eine andere Datei als der aus dem Quellcode gestartete MCP-Server, was zu
|
||||
zwei auseinanderlaufenden Configs führte (die `.exe` zeigte ein anderes
|
||||
Profil 0 als der MCP-Server meldete). Wer hier wieder nach Startweg
|
||||
unterscheidet, baut denselben Bug erneut ein.
|
||||
- **Installierbarkeit verbessert 2026-08-14:** Drei Probleme beim
|
||||
Weitergeben an andere Leute behoben. (1) `build_and_deploy.ps1` starb bei
|
||||
fehlenden Paketen (pyinstaller/pystray/pillow) kommentarlos, v.a. bei
|
||||
|
|
@ -140,7 +173,10 @@ Dokumentation und Verifikation unten für die Größeneinschätzung).
|
|||
Funktion) liefert bei der gebauten `.exe` deren Installationsordner
|
||||
(`sys.executable`-Verzeichnis), sonst den Projektordner (`__file__`-
|
||||
Verzeichnis) -- `DEFAULT_PATH` hängt jetzt daran, landet also immer neben
|
||||
der laufenden Installation. `versapad_data.CONFIG_PATHS` (Lese-Interop
|
||||
der laufenden Installation. **Diese app_dir()-Variante ist seit
|
||||
2026-08-15 überholt und war aktiv schädlich, siehe oben "Config-Pfad
|
||||
darf nie im Installationsverzeichnis liegen".**
|
||||
`versapad_data.CONFIG_PATHS` (Lese-Interop
|
||||
mit der C#-VersaGUI) bleibt bewusst auf dem Desktop, siehe oben. (3) Fehlte
|
||||
die Config UND war kein Board erreichbar, blockierte das Tool mit einer
|
||||
Fehlermeldung statt zu starten. Fix: `load_or_fetch()` legt jetzt bei
|
||||
|
|
@ -154,6 +190,18 @@ Dokumentation und Verifikation unten für die Größeneinschätzung).
|
|||
Namen jetzt immer aus der kombinierten JSON (`combined["profile_names"]`
|
||||
bzw. `versapad_combined.read_profile_names()`), eine einzige Quelle der
|
||||
Wahrheit für alle Frontends.
|
||||
- **Herkunft der drei Punkte oben + Tab-Umbenennen-Fix:** ursprünglich per
|
||||
Cherry-Pick aus Julian Appels `dev/jappel`-Branch auf `main` übernommen
|
||||
(der sich zeitgleich mit dem eigenen COM-Port-Fix entwickelt hatte, kein
|
||||
Fork-Sync-Automatismus -- manuell gegengelesen). Auf `main` bewusst NICHT
|
||||
übernommen wurde damals der `dist/VersaPadViewer`-Build-Zielpfad (statt
|
||||
`%LOCALAPPDATA%\VersaPadViewer`) sowie `.mcp.json` und die `docs/*.md`-
|
||||
Referenzdateien. **2026-08-15: `main` wurde zurück in `dev/jappel`
|
||||
gemerged**, damit landen beide Linien wieder in einem Branch -- inklusive
|
||||
`.mcp.json`, `docs/*.md` und dem `%LOCALAPPDATA%`-Zielpfad (der hat sich
|
||||
im Merge durchgesetzt, siehe Config-Pfad-Bullets oben). Der Notes-Feature-
|
||||
Teil dieser Historie ist der Grund, warum `docs/data-model.md` das
|
||||
`"note"`-Feld nachträglich braucht.
|
||||
- **Bug behoben 2026-08-08:** `server.py` (`vp.load_profile()`) und
|
||||
`desktop_viewer.py` (`_current_profile_view()`) lasen im Nur-Lese-Modus
|
||||
hart von den Desktop-JSONs -- fehlten sie (z.B. User loescht sie), gab es
|
||||
|
|
@ -180,6 +228,24 @@ Dokumentation und Verifikation unten für die Größeneinschätzung).
|
|||
`vcomb.DEFAULT_PATH`, fällt nur bei fehlender/kaputter Datei auf
|
||||
`default_combined()` zurück. Bei jedem "komisches Layout"-Report hier immer
|
||||
ALLE 3 Profile prüfen, nicht nur das gemeldete.
|
||||
- **Randloses Fenster (seit 2026-08-15):** Die Titelleiste ist per reinem Tk
|
||||
`overrideredirect(True)` ausgeblendet -- **niemals** per ctypes/WinAPI
|
||||
nachhelfen (kein `SetWindowLongW`/`ShowWindow` auf das eigene Fenster),
|
||||
siehe Speicher-Notiz "keine Selbstversteck-Fenstertricks": genau diese
|
||||
Kombination hat in einem anderen Projekt Bitdefender-Fehlalarme
|
||||
ausgelöst. Konsequenzen, die mitgebaut werden müssen: kein
|
||||
Taskleisten-Eintrag (Rückweg nur über das Tray-Icon), kein Ziehen am
|
||||
Rahmen (Kopfzeile ist deshalb per `<B1-Motion>` verschiebbar), keine
|
||||
System-Buttons (eigene `✕`/`—` in der Kopfzeile, beide legen ins Tray)
|
||||
und **keine Resize-Ränder**.
|
||||
- **Der Größen-Anfasser hängt per `place()` an der Fensterecke, nicht
|
||||
gepackt am Ende des Inhalts.** Gepackt verschwindet er, sobald das Fenster
|
||||
kleiner als der Inhalt ist -- also exakt dann, wenn man ihn zum
|
||||
Vergrößern bräuchte. `MIN_W/MIN_H` begrenzen das Verkleinern.
|
||||
- Fensterhöhe muss zum Karteninhalt passen: seit die Karten eine Notizzeile
|
||||
haben (`CARD_H` 84 → 114) braucht das Fenster ~960px, sonst liegen
|
||||
Encoder-Bereich und Fußzeile unterhalb des Rands. Wer `CARD_H` ändert,
|
||||
muss `geometry()` mit anpassen.
|
||||
- HID-Tasten-Auswahl im Programmiermodus ist ein Dropdown, kein
|
||||
Tastendruck-Capture (bewusst — kein WinAPI-Hook, um keinen AV-Fehlalarm
|
||||
wie bei den Fensterverstecktricks in anderen Projekten zu riskieren).
|
||||
|
|
@ -230,6 +296,28 @@ Byte-Identität), nicht nur gegen Beispieldaten. Vor jedem Schreibvorgang
|
|||
aufs Board: erst mit unveränderten Daten testen (Identity-Write), bevor
|
||||
echte Änderungen geschrieben werden.
|
||||
|
||||
**Änderungen an der Config immer aus der Sicht prüfen, die die laufende App
|
||||
hat (2026-08-15 gelernt):** Claudes Bash- und PowerShell-Werkzeuge sehen
|
||||
unter `C:\Users\chris\AppData\...` teilweise *unterschiedliche* Dateien —
|
||||
derselbe Pfad lieferte gleichzeitig 29826 Bytes (Bash/MCP-Server) und
|
||||
28455 Bytes (PowerShell/`.exe`). Konkret heißt das: **Config-Schreibvorgänge
|
||||
über den versapad-MCP-Server (`save_local()`) erreichen die installierte
|
||||
`.exe` nicht zuverlässig.** Das hat eine Fehlersuche über viele Runden
|
||||
verschleppt, weil "Notizen sind in der Datei" (Bash) und "App zeigt keine
|
||||
Notizen" gleichzeitig stimmten. Vorgehen:
|
||||
- Config-Dateien, die die installierte App lesen soll, über **PowerShell**
|
||||
schreiben/prüfen (`Get-Item`, dort ausgeführtes `python`), nicht über Bash.
|
||||
- Bei "Änderung wirkt nicht"-Symptomen als Erstes Dateigröße/mtime aus
|
||||
*beiden* Sichten vergleichen, bevor Code-Ursachen gesucht werden.
|
||||
- `Z:\Git\...` (SMB-Share) ist von diesem Effekt nicht betroffen — Quellcode
|
||||
und Build verhalten sich normal.
|
||||
|
||||
Verlässlich zum Ziel führt bei solchen Widersprüchen ein temporäres
|
||||
Diagnose-Modul, das im gebauten Bundle mitläuft und `app_dir()`,
|
||||
`DEFAULT_PATH`, `os.stat()` und den tatsächlich geladenen JSON-Inhalt in eine
|
||||
Datei schreibt — damit war die Ursache in einem Durchlauf sichtbar, nachdem
|
||||
Vermutungen mehrfach danebenlagen.
|
||||
|
||||
## Naming
|
||||
|
||||
Code-Identifier englisch (Python-Konvention: `pack_config`, `read_macros`,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue