fix: window/EXE-Icon zeigte altes Design nach Store-Update 1.0.3 - #5
Conversation
T-20260926-864299616: after the 1.0.3 Store update, the taskbar/tile icon was correct but the window titlebar icon (and the EXE resource feeding it) still showed an old, different design. Root cause (measured, not assumed): assets/cleanmarkdown.ico and its duplicates (CleanMarkdown.ico, DesktopIcon.ico, icon.ico, assets/icon.ico) were generated from an older master image, while store_assets/Square*.png (used by the MSIX manifest for the taskbar tile) got rebranded in a later commit. Each .ico was internally consistent -- same design across all embedded sizes -- which is why this wasn't caught: the mismatch is only visible when comparing the desktop icon against the Store tile, not within one file. Regenerated all five desktop .ico files from store_assets/Square310x310Logo.png (same source, 7 sizes: 16/24/32/48/64/128/256), and added a regression test (test_window_icon_matches_store_tile_branding) that fails if the desktop icon and the Store tile ever drift apart again -- perceptual diff against store_assets/Square310x310Logo.png, threshold 0.20. Measured: broken file diffed by 0.35, this fix by 0.0005. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PTbvD41MCVmnQWaobvHfCk
lukisch
left a comment
There was a problem hiding this comment.
Review (merge-reviewer, claude-opus) auf Head d2f7e20: Die .ico-Korrektur ist richtig, reicht aber noch nicht.
Wer hat recht: Der Nutzer. Ich habe alle 5 .ico in allen 7 eingebetteten Größen alt gegen neu neben Square310x310Logo gerendert. Das alte Icon (auch assets/cleanmarkdown.ico) ist ein braunes Quadrat mit grünem Rahmen, darin ein winziges Dokument-Motiv. Perzeptueller Abstand zur Kachel 0.35 in jeder Größe. Das neue ist das Kachel-Motiv (Dokument mit „M→[ ]“, blau-grüner Verlauf): Abstand 0.00 bei 48/256, 0.01 bei 32, 0.07 bei 16. Bei 16 px ist die Form klar erkennbar, bei 24/32 px auch „M→[ ]“. Die Aussage von heute Mittag, assets/cleanmarkdown.ico sei das richtige, aktuelle Motiv, war falsch.
Mängel:
- Die Master-/Fallback-PNGs tragen weiter das alte Design (Abstand 0.35):
assets/icon.png(1024², Fallback inload_app_icon(), main.py:77),icon.png,DesktopIcon.png(laut CHANGELOG die 1024er „Master-Icons“),assets/favicon.pngsowieassets/favicon.ico. NurCleanMarkdown.pngist aktuell. Das ist vermutlich die eigentliche Rückfallquelle: Wer die .ico wieder aus den „Master-PNGs“ erzeugt, bekommt das alte Design zurück. Bitte in diesem PR aus derselben Quelle neu erzeugen. - Der Regressionstest deckt die tatsächliche Fensterquelle nicht ab:
load_app_icon()probiert zuerstassets/icon.ico, getestet werden aber nurassets/cleanmarkdown.icoundCleanMarkdown.ico, und das nur im 256/128-Frame. Bitte alle getrackten .ico (außer bewusst ausgenommenen), jeweils alle Größen, sowie die Fallback-PNGs gegen die Kachel prüfen. - Gate
_STORE/icon_consistency_check.py(10 Tests grün, Policy 7a schlüssig): Auf diesem PR meldet es „passed … every .ico is internally consistent“, obwohlassets/favicon.iconoch das alte Design trägt (Abstand 0.35). Vermutlich werden .ico ohne 128/256-Frame still übersprungen, PNG-Master prüft es gar nicht. Beides entgegen der Doku („vergleicht jedes .ico“). Bitte Skip melden statt schweigen, PNG-Master mit einbeziehen. - Hinweis zum Release: Kein CHANGELOG-Eintrag, keine Versionsanhebung. Für die Store-Neueinreichung nach 1.0.3 braucht es beides (hier oder im Release-PR).
Review of PR#5 (T-20260926-864299616) found PR#5 only fixed the .ico files load_app_icon() tries first -- the PNG masters/fallbacks it also uses, and the favicon, still carried the pre-fix design and were the actual regression source for anyone hitting the PNG fallback path: - icon.png, DesktopIcon.png, assets/icon.png (1024px masters) - assets/favicon.png, assets/favicon.ico All regenerated from store_assets/Square310x310Logo.png (the same, single source as the .ico fix), master PNGs upscaled 310->1024 via LANCZOS (no higher-resolution source exists in this repo). Test extended (test_window_icon_matches_store_tile_branding) to check every embedded frame of every .ico candidate in load_app_icon()'s fallback chain, plus every master/fallback PNG, against the Store tile -- not just the first two .ico candidates. Version bumped to 1.0.4 (main.py, pyproject.toml, store_package.json, build_exe.bat, tests/test_metadata.py) following the 1.0.3 pattern, CHANGELOG entry added. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PTbvD41MCVmnQWaobvHfCk
lukisch
left a comment
There was a problem hiding this comment.
Re-Review (merge-reviewer, claude-opus) auf Head 29389ac: Merge.
- Alle Desktop-.ico (assets/icon.ico als erste Fensterquelle, cleanmarkdown.ico, CleanMarkdown.ico, icon.ico, DesktopIcon.ico, favicon.ico) sind in allen eingebetteten Größen gegen Square310x310Logo gemessen: Abstand 0.00 (48–256), 0.01 (32), 0.03 (24), 0.07 (16). Die Master- und Fallback-PNGs icon.png, DesktopIcon.png, assets/icon.png, favicon.png, CleanMarkdown.png liegen bei 0.00–0.005, die echten Paket-Kacheln in store_package/CleanMarkdown/icons ebenfalls.
- Tests: 167 passed. Gate-Tests 11 passed. Gate gegen den PR-Stand: passed. Negativkontrolle gegen den alten master: Das Gate meldet jetzt alle alten .ico einschließlich favicon.ico sowie die vier PNG-Master (0.35). CI komplett grün.
- Version 1.0.4 steht in main.py, build_exe.bat, pyproject, store_package.json und den Tests, der CHANGELOG-Eintrag ist korrekt.
Nicht blockierend, als Folgeauftrag:
- Version noch auf 1.0.3 in README.md und README_DE.md (Badge), WINDOWS_STORE_PREP.md und PORTIERUNGSPLAN.md.
- Der Legacy-Spiegel
store_assets/icon_{44x44,50x50,150x150,310x310,310x150}.pngträgt noch das alte Design (Abstand 0.35). Er wird vom echten Paket nicht genutzt (das referenziert store_package/CleanMarkdown/icons, dort ist alles aktuell), das Gate prüft ihn aber nicht. Neu erzeugen oder entfernen. - Die eingecheckten AppxManifest.xml (store_package und store_assets) stehen auf Version="1.0.2.0". Vorbestehend, laut store_assets.py wird das beim Paketbau aus store_package.json erzeugt; vor dem Paketbau trotzdem prüfen, dass im MSIX 1.0.4.0 steht.
….5 (#7) * fix: .md-Dateisymbol zeigte Kachel auf brauner Platte; Store-Paket ohne Dateityp-Zuordnung (1.0.5) T-20260927-699609650. Gemessen, nicht vermutet: - .md -> ProgId CleanMarkdown.mdfile -> DefaultIcon "<CleanMarkdown.exe>,0". Das Symbol ist also das in die EXE eingebackene Icon. Die ausgelieferte 1.0.3-EXE traegt das Plattendesign aus e712d9d (byte-identisch zum CleanMarkdown.ico von b26390d, Abweichung 0.35 zur Store-Kachel). PR #5 hat das nur im Quellbaum behoben, 1.0.4 wurde nie ausgeliefert. - Das installierte 1.0.3-MSIX hat keine FileTypeAssociation, kein resources.pri und keine targetsize/unplated-Varianten: _STORE/msstore_build_msix.ps1 erzeugte das Manifest selbst und ignorierte store_package.json file_types (Builder ausserhalb des Repos mitgefixt). Fix: Version 1.0.5; Square44x44Logo.targetsize-{16..256} je plain, altform-unplated, altform-lightunplated aus der Store-Kachel (scripts/gen_targetsize_icons.py); Regressionstest; STORE_ISSUES korrigiert. Gate (_STORE/icon_consistency_check.py --package) prueft jetzt das gebaute MSIX: rot gegen das installierte 1.0.3 (4 Befunde), gruen gegen 1.0.5. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PTbvD41MCVmnQWaobvHfCk * fix: unplated targetsize-Assets waren opak; Migrationspfad für lokale Installation T-20260927-699609650, Blocker D aus der astra-Abnahme von PR #7 (81dacc6): - install_local.ps1 registriert eine eigene ProgID (CleanMarkdown.mdfile, DefaultIcon auf die lokale EXE). Diese Installation blieb nach einem Store-Update unverändert bestehen und "gewann" weiterhin die .md-Zuordnung -- das MSIX ersetzt sie nicht automatisch. uninstall_local.ps1 ist das Gegenstück: bricht ab, wenn kein Store-Paket installiert ist, sichert die betroffenen Registry-Zweige per reg export und entfernt danach nur, was install_local.ps1 selbst angelegt hat (ProgID, DefaultIcon, .md-Verweis, OpenWithProgids, Applications-Key, UserChoice falls zutreffend, Startmenü- Verknüpfung, Installationsordner). README/README_DE dokumentieren jetzt, dass lokale und Store-Installation nicht parallel bestehen sollen. - gen_targetsize_icons.py erzeugte für unplated/lightunplated-Varianten byte-identische, opake Kopien der plated-Variante -- ein Nebenbefund der Gate-Härtung in _STORE/icon_consistency_check.py (siehe dortigen Commit): das jetzt strengere --package-Gate hätte den eigenen 1.0.5-Build andernfalls selbst abgelehnt. Fix: kleiner transparenter Eckpatch pro Variante -- genug für echte Transparenz, klein genug, um innerhalb der bereits kalibrierten Diff-Schwelle von test_assets_and_icons.py zu bleiben (ein voller 12%-Rand ergab 0.22 bei 16px, Schwelle 0.20). Verifiziert: 168 Projekttests grün; echter 1.0.5-MSIX-Neubau über das gehärtete _STORE/msstore_build_msix.ps1 (inkl. erzwungenem icon_consistency_check.py --package) läuft mit Exit 0 durch. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PTbvD41MCVmnQWaobvHfCk * fix: 2. astra-Abnahme (5 Blocker) schliessen — C1/C2/D1-D3 T-20260927-699609650, Head 9596928 wurde von gpt-6-astra (effort high) mit "NICHT OK" bewertet (voller Bericht: _codex/ASTRA-REABNAHME_T-20260927-699609650.md). Alle 5 Blocker sind behoben und gegen astras real reproduzierte Manipulationen verifiziert (Details: _codex/FIX-C1-C2-D1-D2-D3_T-20260927-699609650.md): - C1: Gate pruefte nur 5 von 14 ausgelieferten Icon-Groessen -- jetzt werden alle tatsaechlich im Paket/resources.pri vorhandenen Varianten erkannt und geprueft, nicht nur eine feste Pflichtliste. - C2: Das reale 1.0.5-MSIX enthielt den onedir-Laufzeitordner (_internal, Python-DLLs) nicht -- die App waere nicht gestartet. Kopierschritt erkennt jetzt onedir-Layout und uebernimmt den kompletten Ordner. - D1: uninstall_local.ps1 loeschte beim UserChoice-Rueckbau den gesamten Explorer-Elternzweig FileExts\.md samt fremden Geschwisterzweigen -- jetzt nur noch der UserChoice-Unterschluessel selbst. - D2: Fehlgeschlagene Registry-Backups stoppten die Loeschung nicht -- jeder Export wird jetzt geprueft, ein Fehlschlag bricht vor jeder Aenderung ab. - D3: Jede installierte Store-Version wurde akzeptiert, auch die real installierte 1.0.3 ohne .md-FileTypeAssociation -- das Manifest wird jetzt geprueft, eine Version ohne Handler wird abgelehnt. D1-D3 zusaetzlich per gemocktem PowerShell-Testlauf verifiziert (kein echter Registry-Zugriff). Store-Gate-Tests 27/27 gruen, Projekt-Testsuite 168/168 gruen, realer 1.0.5-MSIX-Neubau ueber das gehaertete msstore_build_msix.ps1 gruen. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PTbvD41MCVmnQWaobvHfCk * fix: uninstall_local.ps1 loeschte .md-Standardwert nicht wirklich (D4) T-20260927-699609650, 3. Abnahme (Fable, schreibgeschuetzt) fand: mein D1-Fix `Remove-ItemProperty -Name "(Default)"` schlaegt gegen den PowerShell- Registry-Provider fehl (verifiziert in pwsh 7.6.6 und Windows PowerShell 5.1), `-ErrorAction SilentlyContinue` machte das unsichtbar. Folge: HKCU:\Software\ Classes\.md zeigte nach dem Rueckbau weiter auf die bereits geloeschte ProgID CleanMarkdown.mdfile -- schlimmer als der vorherige Set-Item -Value "" (der den Verweis wenigstens leerte). Fix: echte Entfernung ueber die .NET-Registry-API ([Microsoft.Win32.Registry]::CurrentUser...DeleteValue), die den PowerShell- Provider umgeht. Verifiziert in einem Wegwerf-Schluessel (angelegt, geprueft, wieder entfernt -- keine dauerhafte Aenderung am Host). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PTbvD41MCVmnQWaobvHfCk * chore: internal review reports aus dem Repo entfernen, README neutralisieren merge-reviewer-Befund vor dem Merge von PR #7: Das Repo ist public. _codex/ enthielt interne Abnahmeberichte mit lokalen Pfaden, Hostnamen und Reviewernamen -- nach einem Squash-Merge waeren die dauerhaft in der main-Historie gelandet. - _codex/ aus dem Git-Tracking entfernt (git rm --cached), lokal behalten, in .gitignore aufgenommen. - README.md/README_DE.md: interne Ticket-ID und Reviewername ("astra abnahme review") aus der Nutzer-Doku entfernt/neutralisiert. Die Ticket-ID bleibt wie besprochen im CHANGELOG stehen. Fachliche Pruefung wird durch diesen Commit nicht beruehrt (reine Bereinigung, kein Verhaltensunterschied). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PTbvD41MCVmnQWaobvHfCk --------- Co-authored-by: Lukas Geiger <lukas@um-bruch.org> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Zusammenfassung
das Taskleisten-/Kachel-Icon korrekt ist, das Fenster-Icon (Titelleiste,
EXE-Ressource) aber ein altes, anderes Design zeigt -- ein Ruckfall
gegenuber dem letzten Store-Paket.
(
store_assets/Square*.png) wurde in einem spaeteren Commit neugebrandet, das Desktop-Icon-Material (
.ico-Dateien UND dieMaster-/Fallback-PNGs, die
load_app_icon()in main.py als Kandidatendurchgeht) wurde dabei nicht mitgezogen. Jede einzelne Datei war fuer
sich konsistent (alle eingebetteten Groessen/Aufloesungen zeigten
dasselbe -- alte -- Design), weshalb ein reiner Selbstvergleich das nie
gefunden hatte -- erst der Quervergleich Desktop-Icon <-> Store-Kachel
zeigt den Bruch.
d2f7e20: die fuenf Desktop-.ico-Dateien(
assets/cleanmarkdown.ico,CleanMarkdown.ico,DesktopIcon.ico,icon.ico,assets/icon.ico) ausstore_assets/Square310x310Logo.pngneu erzeugt.
29389ac(Review-Nachbesserung): die verbleibenden, im ersten Commituebersehenen Fallback-Assets aus derselben Quelle neu erzeugt --
icon.png/DesktopIcon.png/assets/icon.png(1024px-Master,310->1024 hochskaliert, da keine hoeher aufgeloeste Quelle im Repo
existiert) sowie
assets/favicon.png/assets/favicon.ico. PlusVersionsbump auf 1.0.4 (main.py, pyproject.toml, store_package.json,
build_exe.bat, tests/test_metadata.py) und CHANGELOG-Eintrag, nach dem
Muster des 1.0.3-Release-Commits.
test_window_icon_matches_store_tile_brandingintests/test_assets_and_icons.pyprueft jetzt jeden Frame jeder.ico-Datei inload_app_icon()s Fallback-Kette PLUS jedeMaster-/Fallback-PNG gegen die Store-Kachel (perzeptueller Diff,
Schwelle 0.20). Prueft damit direkt die Pixel, die Windows tatsaechlich
zeichnet (EXE-Ressource + Fenster-Titelleiste), nicht nur "ein QIcon
existiert". 167/167 Tests im Projekt gruen.
Zusaetzlich (nicht Teil dieses Fixes, nur zur Kenntnis)
mobile_icons/*(aeltere olivbraune Gestaltung fuer PWA/Web) wurdebewusst NICHT angefasst -- andere Verbrauchsstelle (mobil/Web statt
Desktop-Fenster), separater Befund.
Release-Gate
Das generische Release-Gate-Skript (
icon_consistency_check.py,.SOFTWARE/_STORE/) wurde im selben Review-Zug nachgebessert: esuebersah zuvor genau diese Luecke (favicon-grosse
.ico-Dateien ohne128/256px-Frame wurden stillschweigend uebersprungen, Master-PNGs
wurden gar nicht geprueft) und ist jetzt in
WINDOWS_STORE_BUGFIX_POLICY.mdAbschnitt 7a als Pflichtschritt vor jeder Store-Einreichung verankert.
Test plan
python -m pytest -q-- 167 passedpython icon_consistency_check.py <worktree>-- "gate passed"🤖 Generated with Claude Code
https://claude.ai/code/session_01PTbvD41MCVmnQWaobvHfCk