diff --git a/AGENTS.md b/AGENTS.md index 05fd16f..fdfc96a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -29,7 +29,14 @@ Nutzerorientierte Einführung: [`README.md`](README.md). Makros per 8-Byte-Paket-Protokoll, Board-Identifikation per VID/PID `239A:0042`. Schreiben ist sicher im Sinne von "kann NVM nicht zerlegen" — Firmware prüft Magic/CRC/Keycode-Bereich vor jedem Save, antwortet - sonst nur mit NACK. + sonst nur mit NACK. `read_active_profile()` (für Live-Sync-Polling) + nutzt seit 2026-08-07 `CMD_READ_STATUS`/`EVT_STATUS` (0x06/0x86, ein + Antwortpaket) statt eines vollen `CONFIG_READ`-Dumps (124 Pakete) — + Letzterer blockiert die Firmware in `poll_vendor()` lang genug, dass + laufende LED-Pulse-Animationen sichtbar stottern (Root Cause + Fix in + VersaMCU-Commit "Add lightweight READ_STATUS command..."). **Braucht + entsprechend neue Firmware auf dem Board** — mit altem `versapad`-Firmwarestand + liefert `READ_STATUS` schlicht Timeout, kein Absturz. - `versapad_combined.py` — Ein-Datei-Format (alle 3 Profile + Makros + **nur lokal gespeicherte** Profilnamen), Default-Pfad `~\OneDrive\Desktop\versapad_config_all.json`. Passt zum Wire-Protokoll: @@ -86,6 +93,18 @@ 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". +- **Bug behoben 2026-08-07:** `_on_toggle_editing()` initialisierte + `self.combined` beim ersten Aktivieren des Programmiermodus mit + `vcomb.default_combined()` — das seedet ALLE 3 Profile aus den alten + Einzel-JSONs `versapad_config{1,2,3}.json`, nicht aus der aktuellen + `versapad_config_all.json` oder vom Board. Ein Klick auf "Zum Board + übertragen" hat dadurch beim Testen alle 3 Profile auf einen veralteten + Stand zurückgesetzt, obwohl nur ein Profil-Tab sichtbar bearbeitet wurde — + der Schaden an den anderen beiden Profilen blieb unbemerkt, bis explizit + jedes Profil einzeln gegengelesen wurde. Fix: lädt jetzt zuerst + `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. - 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). @@ -189,3 +208,13 @@ Committen: prägnante Commit-Message je abgeschlossenem, verifiziertem Arbeitspaket. Nach jedem Push: alle bekannten Remotes prüfen (`origin` auf GitHub, `jappel` auf git.jappel.io) — beide müssen synchron bleiben, siehe Speicher-Notiz "Multi-Remote-Repos synchron halten". + +**PR-Erstellung auf git.jappel.io per API/curl mit Access-Token wird vom +Bash-Classifier geblockt** (Auto-Mode, gilt auch für `git credential fill`), +siehe Speicher-Notiz "Bash-Klassifikator blockt Credential/Auth-Schreibzugriffe". +Branch pushen geht (nutzt den Git-eigenen Credential-Helper, kein Token im +Klartext im Bash-Aufruf), den fertigen PR muss der User über den von Forgejo +nach dem Push ausgegebenen Compare-Link selbst anlegen (oder Claude einen +Token geben, der dann NICHT wiederverwendbar im Bash-Aufruf landen darf, +sondern nur für den einen `curl`-Call — auch das kann der Classifier trotzdem +blocken, dann bleibt nur der manuelle Link). diff --git a/desktop_viewer.py b/desktop_viewer.py index 1b80b6d..008b2c7 100644 --- a/desktop_viewer.py +++ b/desktop_viewer.py @@ -391,7 +391,13 @@ class VersaPadViewer(tk.Tk): self._on_toggle_sync() self.sync_check.configure(state="disabled") if self.combined is None: - self.combined = vcomb.default_combined() + if os.path.exists(vcomb.DEFAULT_PATH): + try: + self.combined = vcomb.load_file(vcomb.DEFAULT_PATH) + except (OSError, ValueError, KeyError): + self.combined = vcomb.default_combined() + else: + self.combined = vcomb.default_combined() self.prog_row.pack(fill="x", padx=20, pady=(0, 14), after=self.tabs) self.header_sub.configure(text="Programmiermodus · Zelle anklicken zum Bearbeiten") else: