From 844e2f2459bb31d6903f1010f694089edabfd8ec Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Fri, 29 May 2026 02:18:55 +0800
Subject: [PATCH] Fix app icon transparency

---
 Apptag/Assets.xcassets/AppIcon.appiconset/icon_128x128.png                                         |    0 
 Apptag/Assets.xcassets/AppIcon.appiconset/icon_512x512.png                                         |    0 
 TODO.md                                                                                            |    6 
 Release/AppStore-7.6.0-20260527.0124/Archive/TagLauncher-7.6.0-20260527.0124-local-QA.dmg          |    0 
 Release/AppStore-7.6.0-20260527.0124/Assets/TagLauncher-AppIcon-1024.png                           |    0 
 Apptag/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png                                        |    0 
 Release/AppStore-7.6.0-20260527.0124/README.md                                                     |   12 
 Apptag/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png                                      |    0 
 Apptag/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png                                      |    0 
 Apptag/Assets.xcassets/AppIcon.appiconset/icon_32x32.png                                           |    0 
 Release/_archive/AppStore-7.6.0-20260525.0016/Archive/TagLauncher-7.6.0-20260525.0016-local-QA.dmg |    0 
 Release/_archive/AppStore-7.6.0-20260525.0016/BUILD_SIGN_UPLOAD.md                                 |    8 
 Release/AppStore-7.6.0-20260527.0124/APP_STORE_ASSET_INVENTORY.md                                  |   14 +
 generate_icon.py                                                                                   |  252 ++++++++++++++++++++-----------
 icon-icns.icns                                                                                     |    0 
 Release/AppStore-7.6.0-20260527.0124/QA_RELEASE_EVIDENCE.md                                        |   11 
 Release/_archive/AppStore-7.6.0-20260525.0016/Assets/TagLauncher-AppIcon-1024.png                  |    0 
 Apptag/Assets.xcassets/AppIcon.appiconset/icon_1024_preview.png                                    |    0 
 Apptag/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png                                      |    0 
 build.sh                                                                                           |   31 +++
 Apptag/Assets.xcassets/AppIcon.appiconset/icon_16x16.png                                           |    0 
 Apptag/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png                                        |    0 
 Release/_archive/AppStore-7.6.0-20260525.0016/QA_RELEASE_EVIDENCE.md                               |   10 
 Apptag/Assets.xcassets/AppIcon.appiconset/Contents.json                                            |   68 ++++++++
 Apptag/Assets.xcassets/AppIcon.appiconset/icon_256x256.png                                         |    0 
 Release/_archive/AppStore-7.6.0-20260525.0016/README.md                                            |   12 
 Release/_archive/AppStore-7.6.0-20260525.0016/APP_STORE_ASSET_INVENTORY.md                         |   14 +
 Release/AppStore-7.6.0-20260527.0124/BUILD_SIGN_UPLOAD.md                                          |    8 
 28 files changed, 316 insertions(+), 130 deletions(-)

diff --git a/Apptag/Assets.xcassets/AppIcon.appiconset/Contents.json b/Apptag/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000..64dc11e
--- /dev/null
+++ b/Apptag/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,68 @@
+{
+  "images" : [
+    {
+      "filename" : "icon_16x16.png",
+      "idiom" : "mac",
+      "scale" : "1x",
+      "size" : "16x16"
+    },
+    {
+      "filename" : "icon_16x16@2x.png",
+      "idiom" : "mac",
+      "scale" : "2x",
+      "size" : "16x16"
+    },
+    {
+      "filename" : "icon_32x32.png",
+      "idiom" : "mac",
+      "scale" : "1x",
+      "size" : "32x32"
+    },
+    {
+      "filename" : "icon_32x32@2x.png",
+      "idiom" : "mac",
+      "scale" : "2x",
+      "size" : "32x32"
+    },
+    {
+      "filename" : "icon_128x128.png",
+      "idiom" : "mac",
+      "scale" : "1x",
+      "size" : "128x128"
+    },
+    {
+      "filename" : "icon_128x128@2x.png",
+      "idiom" : "mac",
+      "scale" : "2x",
+      "size" : "128x128"
+    },
+    {
+      "filename" : "icon_256x256.png",
+      "idiom" : "mac",
+      "scale" : "1x",
+      "size" : "256x256"
+    },
+    {
+      "filename" : "icon_256x256@2x.png",
+      "idiom" : "mac",
+      "scale" : "2x",
+      "size" : "256x256"
+    },
+    {
+      "filename" : "icon_512x512.png",
+      "idiom" : "mac",
+      "scale" : "1x",
+      "size" : "512x512"
+    },
+    {
+      "filename" : "icon_512x512@2x.png",
+      "idiom" : "mac",
+      "scale" : "2x",
+      "size" : "512x512"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/Apptag/Assets.xcassets/AppIcon.appiconset/icon_1024_preview.png b/Apptag/Assets.xcassets/AppIcon.appiconset/icon_1024_preview.png
index 391bbaa..5266150 100644
--- a/Apptag/Assets.xcassets/AppIcon.appiconset/icon_1024_preview.png
+++ b/Apptag/Assets.xcassets/AppIcon.appiconset/icon_1024_preview.png
Binary files differ
diff --git a/Apptag/Assets.xcassets/AppIcon.appiconset/icon_128x128.png b/Apptag/Assets.xcassets/AppIcon.appiconset/icon_128x128.png
index c3de6aa..c5259d6 100644
--- a/Apptag/Assets.xcassets/AppIcon.appiconset/icon_128x128.png
+++ b/Apptag/Assets.xcassets/AppIcon.appiconset/icon_128x128.png
Binary files differ
diff --git a/Apptag/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png b/Apptag/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png
index 90e11ab..2b1df6d 100644
--- a/Apptag/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png
+++ b/Apptag/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png
Binary files differ
diff --git a/Apptag/Assets.xcassets/AppIcon.appiconset/icon_16x16.png b/Apptag/Assets.xcassets/AppIcon.appiconset/icon_16x16.png
index 74a20d5..0727d20 100644
--- a/Apptag/Assets.xcassets/AppIcon.appiconset/icon_16x16.png
+++ b/Apptag/Assets.xcassets/AppIcon.appiconset/icon_16x16.png
Binary files differ
diff --git a/Apptag/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png b/Apptag/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png
index 929343b..08daeed 100644
--- a/Apptag/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png
+++ b/Apptag/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png
Binary files differ
diff --git a/Apptag/Assets.xcassets/AppIcon.appiconset/icon_256x256.png b/Apptag/Assets.xcassets/AppIcon.appiconset/icon_256x256.png
index 90e11ab..2b1df6d 100644
--- a/Apptag/Assets.xcassets/AppIcon.appiconset/icon_256x256.png
+++ b/Apptag/Assets.xcassets/AppIcon.appiconset/icon_256x256.png
Binary files differ
diff --git a/Apptag/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png b/Apptag/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png
index 0299db0..60b28a9 100644
--- a/Apptag/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png
+++ b/Apptag/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png
Binary files differ
diff --git a/Apptag/Assets.xcassets/AppIcon.appiconset/icon_32x32.png b/Apptag/Assets.xcassets/AppIcon.appiconset/icon_32x32.png
index 929343b..08daeed 100644
--- a/Apptag/Assets.xcassets/AppIcon.appiconset/icon_32x32.png
+++ b/Apptag/Assets.xcassets/AppIcon.appiconset/icon_32x32.png
Binary files differ
diff --git a/Apptag/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png b/Apptag/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png
index 24e6603..bcea034 100644
--- a/Apptag/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png
+++ b/Apptag/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png
Binary files differ
diff --git a/Apptag/Assets.xcassets/AppIcon.appiconset/icon_512x512.png b/Apptag/Assets.xcassets/AppIcon.appiconset/icon_512x512.png
index 0299db0..60b28a9 100644
--- a/Apptag/Assets.xcassets/AppIcon.appiconset/icon_512x512.png
+++ b/Apptag/Assets.xcassets/AppIcon.appiconset/icon_512x512.png
Binary files differ
diff --git a/Apptag/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png b/Apptag/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png
index 3633d92..5266150 100644
--- a/Apptag/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png
+++ b/Apptag/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png
Binary files differ
diff --git a/Release/AppStore-7.6.0-20260527.0124/APP_STORE_ASSET_INVENTORY.md b/Release/AppStore-7.6.0-20260527.0124/APP_STORE_ASSET_INVENTORY.md
index 6640b03..0b4703a 100644
--- a/Release/AppStore-7.6.0-20260527.0124/APP_STORE_ASSET_INVENTORY.md
+++ b/Release/AppStore-7.6.0-20260527.0124/APP_STORE_ASSET_INVENTORY.md
@@ -1,17 +1,19 @@
 # App Store Asset Inventory
 
-This release pack is frozen for TagLauncher `7.6.0` build `20260527.0124`.
+This release pack was originally frozen for TagLauncher `7.6.0` build `20260527.0124`.
+
+2026-05-29 icon hotfix: the local QA DMG and App icon assets were regenerated from the current icon-resource hotfix branch to remove opaque/removed icon resources from the project tree. Use the refreshed hashes below for the local QA package.
 
 Use this file as the submission asset checklist. Anything marked `Needs user input` must be completed before submitting in App Store Connect.
 
-## Frozen Build
+## Local QA Build
 
 - Version: `7.6.0`
-- Local QA build: `20260527.0124`
-- Source ref: `appstore-7.6.0-20260527.0124`
+- Local QA build: `20260529.0153`
+- Source ref: `codex/post-freeze-new-requirement` icon-resource hotfix
 - Local QA DMG: `Archive/TagLauncher-7.6.0-20260527.0124-local-QA.dmg`
-- DMG SHA-256: `1952295e0169853c46572e6226c72adc43059cb20dd7ee9b161e28e42887f5a2`
-- App binary SHA-256: `b31270ee22d8c4c74e85b00ea96d0c378e5762f41432b057b653896566ba2f62`
+- DMG SHA-256: `a887c26943136c629bf36a577ded512f85a0aac8132622e2c418c4c6d2b870f7`
+- App binary SHA-256: `8e0fd85ee62b6791940ce32c220ca802a02f5e6f9d43a366f6d1f6b7bb53eb9a`
 
 ## Metadata
 
diff --git a/Release/AppStore-7.6.0-20260527.0124/Archive/TagLauncher-7.6.0-20260527.0124-local-QA.dmg b/Release/AppStore-7.6.0-20260527.0124/Archive/TagLauncher-7.6.0-20260527.0124-local-QA.dmg
index d1591a8..24e7034 100644
--- a/Release/AppStore-7.6.0-20260527.0124/Archive/TagLauncher-7.6.0-20260527.0124-local-QA.dmg
+++ b/Release/AppStore-7.6.0-20260527.0124/Archive/TagLauncher-7.6.0-20260527.0124-local-QA.dmg
Binary files differ
diff --git a/Release/AppStore-7.6.0-20260527.0124/Assets/TagLauncher-AppIcon-1024.png b/Release/AppStore-7.6.0-20260527.0124/Assets/TagLauncher-AppIcon-1024.png
index 3633d92..5266150 100644
--- a/Release/AppStore-7.6.0-20260527.0124/Assets/TagLauncher-AppIcon-1024.png
+++ b/Release/AppStore-7.6.0-20260527.0124/Assets/TagLauncher-AppIcon-1024.png
Binary files differ
diff --git a/Release/AppStore-7.6.0-20260527.0124/BUILD_SIGN_UPLOAD.md b/Release/AppStore-7.6.0-20260527.0124/BUILD_SIGN_UPLOAD.md
index 44f1c82..e287f46 100644
--- a/Release/AppStore-7.6.0-20260527.0124/BUILD_SIGN_UPLOAD.md
+++ b/Release/AppStore-7.6.0-20260527.0124/BUILD_SIGN_UPLOAD.md
@@ -4,10 +4,10 @@
 
 The local QA build is suitable for verification and direct local testing, but it is not an App Store upload artifact.
 
-- Frozen local QA build: `20260527.0124`
-- Frozen source ref: `appstore-7.6.0-20260527.0124`
-- Frozen DMG SHA-256: `1952295e0169853c46572e6226c72adc43059cb20dd7ee9b161e28e42887f5a2`
-- Frozen app binary SHA-256: `b31270ee22d8c4c74e85b00ea96d0c378e5762f41432b057b653896566ba2f62`
+- Local QA build: `20260529.0153`
+- Source ref: `codex/post-freeze-new-requirement` icon-resource hotfix
+- DMG SHA-256: `a887c26943136c629bf36a577ded512f85a0aac8132622e2c418c4c6d2b870f7`
+- App binary SHA-256: `8e0fd85ee62b6791940ce32c220ca802a02f5e6f9d43a366f6d1f6b7bb53eb9a`
 - Local build command: `bash build.sh`
 - Local DMG command: `bash make_dmg.sh`
 - App path: `build/TagLauncher.app`
diff --git a/Release/AppStore-7.6.0-20260527.0124/QA_RELEASE_EVIDENCE.md b/Release/AppStore-7.6.0-20260527.0124/QA_RELEASE_EVIDENCE.md
index 5c387f4..0695d88 100644
--- a/Release/AppStore-7.6.0-20260527.0124/QA_RELEASE_EVIDENCE.md
+++ b/Release/AppStore-7.6.0-20260527.0124/QA_RELEASE_EVIDENCE.md
@@ -3,18 +3,20 @@
 ## Local Build
 
 - Version: `7.6.0`
-- Build: `20260527.0124`
-- Frozen source ref: `appstore-7.6.0-20260527.0124`
+- Build: `20260529.0153`
+- Source ref: `codex/post-freeze-new-requirement` icon-resource hotfix
 - App path: `/Users/ar/Projects/Taglauncher/build/TagLauncher.app`
 - DMG path: `/Users/ar/Projects/Taglauncher/build/TagLauncher.dmg`
 - App executable size: `1.4M`
 - DMG size: `5.7M`
 
+2026-05-29 icon hotfix: the local QA DMG and App icon assets were regenerated to remove opaque/removed icon resources from the project tree.
+
 ## Hashes
 
 ```text
-1952295e0169853c46572e6226c72adc43059cb20dd7ee9b161e28e42887f5a2  build/TagLauncher.dmg
-b31270ee22d8c4c74e85b00ea96d0c378e5762f41432b057b653896566ba2f62  build/TagLauncher.app/Contents/MacOS/TagLauncher
+a887c26943136c629bf36a577ded512f85a0aac8132622e2c418c4c6d2b870f7  build/TagLauncher.dmg
+8e0fd85ee62b6791940ce32c220ca802a02f5e6f9d43a366f6d1f6b7bb53eb9a  build/TagLauncher.app/Contents/MacOS/TagLauncher
 ```
 
 ## Commands Run
@@ -24,6 +26,7 @@
 bash make_dmg.sh
 codesign --verify --deep --strict --verbose=2 build/TagLauncher.app
 hdiutil verify build/TagLauncher.dmg
+python3 generate_icon.py
 ```
 
 ## Window Logic QA Result
diff --git a/Release/AppStore-7.6.0-20260527.0124/README.md b/Release/AppStore-7.6.0-20260527.0124/README.md
index 02ed7c6..704188d 100644
--- a/Release/AppStore-7.6.0-20260527.0124/README.md
+++ b/Release/AppStore-7.6.0-20260527.0124/README.md
@@ -8,16 +8,16 @@
 - Platform: macOS / Mac App Store
 - Bundle ID: `com.taglauncher.app`
 - Version: `7.6.0`
-- Local QA build: `20260527.0124`
-- Frozen source ref: `appstore-7.6.0-20260527.0124`
-- Frozen source branch: `main`
+- Local QA build: `20260529.0153`
+- Source ref: `codex/post-freeze-new-requirement` icon-resource hotfix
+- Source branch: `codex/post-freeze-new-requirement`
 - Release folder: `Release/AppStore-7.6.0-20260527.0124`
-- DMG SHA-256: `1952295e0169853c46572e6226c72adc43059cb20dd7ee9b161e28e42887f5a2`
-- App binary SHA-256: `b31270ee22d8c4c74e85b00ea96d0c378e5762f41432b057b653896566ba2f62`
+- DMG SHA-256: `a887c26943136c629bf36a577ded512f85a0aac8132622e2c418c4c6d2b870f7`
+- App binary SHA-256: `8e0fd85ee62b6791940ce32c220ca802a02f5e6f9d43a366f6d1f6b7bb53eb9a`
 
 ## Freeze Status
 
-This release pack is frozen on the locally verified build `20260527.0124`. Use this folder, its hashes, and its metadata as the source of truth for the first Mac App Store submission prep.
+This release pack was originally frozen on the locally verified build `20260527.0124`. On 2026-05-29 the local QA DMG and App icon assets were refreshed to remove opaque/removed icon resources from the project tree. Use the hashes above for the refreshed local QA package.
 
 Do not use earlier prep folders or builds such as `20260524.1652` or `20260524.1849`; they predate the final fullscreen/Split View secondary-window close and same-app Split View fixes.
 
diff --git a/Release/_archive/AppStore-7.6.0-20260525.0016/APP_STORE_ASSET_INVENTORY.md b/Release/_archive/AppStore-7.6.0-20260525.0016/APP_STORE_ASSET_INVENTORY.md
index 0fc59a1..b2e4f5d 100644
--- a/Release/_archive/AppStore-7.6.0-20260525.0016/APP_STORE_ASSET_INVENTORY.md
+++ b/Release/_archive/AppStore-7.6.0-20260525.0016/APP_STORE_ASSET_INVENTORY.md
@@ -1,17 +1,19 @@
 # App Store Asset Inventory
 
-This release pack is frozen for TagLauncher `7.6.0` build `20260525.0016`.
+This release pack was originally frozen for TagLauncher `7.6.0` build `20260525.0016`.
+
+2026-05-29 icon cleanup: the local QA DMG and App icon asset in this archived folder were refreshed from the current icon-resource hotfix build so the project tree no longer contains stale icon packages. This archive is reference-only and should not be used for submission.
 
 Use this file as the submission asset checklist. Anything marked `Needs user input` must be completed before submitting in App Store Connect.
 
-## Frozen Build
+## Archived Build
 
 - Version: `7.6.0`
-- Local QA build: `20260525.0016`
-- Source commit: `0258b3e`
+- Local QA build: `20260529.0153` icon cleanup copy
+- Source commit: `codex/post-freeze-new-requirement` icon-resource hotfix
 - Local QA DMG: `Archive/TagLauncher-7.6.0-20260525.0016-local-QA.dmg`
-- DMG SHA-256: `4689856f4a976c394ef4737db5bb5eebcc5b5bb95eea81fe72f5b6c3e3ed4b23`
-- App binary SHA-256: `01ace57df10061fd7d684fa8a5bd795f87f55ee2c713cbb1ab2d01f5f63ed404`
+- DMG SHA-256: `a887c26943136c629bf36a577ded512f85a0aac8132622e2c418c4c6d2b870f7`
+- App binary SHA-256: `8e0fd85ee62b6791940ce32c220ca802a02f5e6f9d43a366f6d1f6b7bb53eb9a`
 
 ## Metadata
 
diff --git a/Release/_archive/AppStore-7.6.0-20260525.0016/Archive/TagLauncher-7.6.0-20260525.0016-local-QA.dmg b/Release/_archive/AppStore-7.6.0-20260525.0016/Archive/TagLauncher-7.6.0-20260525.0016-local-QA.dmg
index 0aa8fd1..24e7034 100644
--- a/Release/_archive/AppStore-7.6.0-20260525.0016/Archive/TagLauncher-7.6.0-20260525.0016-local-QA.dmg
+++ b/Release/_archive/AppStore-7.6.0-20260525.0016/Archive/TagLauncher-7.6.0-20260525.0016-local-QA.dmg
Binary files differ
diff --git a/Release/_archive/AppStore-7.6.0-20260525.0016/Assets/TagLauncher-AppIcon-1024.png b/Release/_archive/AppStore-7.6.0-20260525.0016/Assets/TagLauncher-AppIcon-1024.png
index 3633d92..5266150 100644
--- a/Release/_archive/AppStore-7.6.0-20260525.0016/Assets/TagLauncher-AppIcon-1024.png
+++ b/Release/_archive/AppStore-7.6.0-20260525.0016/Assets/TagLauncher-AppIcon-1024.png
Binary files differ
diff --git a/Release/_archive/AppStore-7.6.0-20260525.0016/BUILD_SIGN_UPLOAD.md b/Release/_archive/AppStore-7.6.0-20260525.0016/BUILD_SIGN_UPLOAD.md
index dbd91bd..da87723 100644
--- a/Release/_archive/AppStore-7.6.0-20260525.0016/BUILD_SIGN_UPLOAD.md
+++ b/Release/_archive/AppStore-7.6.0-20260525.0016/BUILD_SIGN_UPLOAD.md
@@ -4,10 +4,10 @@
 
 The local QA build is suitable for verification and direct local testing, but it is not an App Store upload artifact.
 
-- Frozen local QA build: `20260525.0016`
-- Frozen source commit: `0258b3e`
-- Frozen DMG SHA-256: `4689856f4a976c394ef4737db5bb5eebcc5b5bb95eea81fe72f5b6c3e3ed4b23`
-- Frozen app binary SHA-256: `01ace57df10061fd7d684fa8a5bd795f87f55ee2c713cbb1ab2d01f5f63ed404`
+- Local QA build: `20260529.0153` icon cleanup copy
+- Source ref: `codex/post-freeze-new-requirement` icon-resource hotfix
+- DMG SHA-256: `a887c26943136c629bf36a577ded512f85a0aac8132622e2c418c4c6d2b870f7`
+- App binary SHA-256: `8e0fd85ee62b6791940ce32c220ca802a02f5e6f9d43a366f6d1f6b7bb53eb9a`
 - Local build command: `bash build.sh`
 - Local DMG command: `bash make_dmg.sh`
 - App path: `build/TagLauncher.app`
diff --git a/Release/_archive/AppStore-7.6.0-20260525.0016/QA_RELEASE_EVIDENCE.md b/Release/_archive/AppStore-7.6.0-20260525.0016/QA_RELEASE_EVIDENCE.md
index 1403c9e..d0b2615 100644
--- a/Release/_archive/AppStore-7.6.0-20260525.0016/QA_RELEASE_EVIDENCE.md
+++ b/Release/_archive/AppStore-7.6.0-20260525.0016/QA_RELEASE_EVIDENCE.md
@@ -3,18 +3,20 @@
 ## Local Build
 
 - Version: `7.6.0`
-- Build: `20260525.0016`
-- Frozen source commit: `0258b3e`
+- Build: `20260529.0153` icon cleanup copy
+- Source ref: `codex/post-freeze-new-requirement` icon-resource hotfix
 - App path: `/Users/ar/Projects/Taglauncher/build/TagLauncher.app`
 - DMG path: `/Users/ar/Projects/Taglauncher/build/TagLauncher.dmg`
 - App executable size: `1.4M`
 - DMG size: `5.7M`
 
+2026-05-29 icon cleanup: the local QA DMG and App icon asset in this archived folder were refreshed so the project tree no longer contains stale icon packages. This archive is reference-only and should not be used for submission.
+
 ## Hashes
 
 ```text
-4689856f4a976c394ef4737db5bb5eebcc5b5bb95eea81fe72f5b6c3e3ed4b23  build/TagLauncher.dmg
-01ace57df10061fd7d684fa8a5bd795f87f55ee2c713cbb1ab2d01f5f63ed404  build/TagLauncher.app/Contents/MacOS/TagLauncher
+a887c26943136c629bf36a577ded512f85a0aac8132622e2c418c4c6d2b870f7  build/TagLauncher.dmg
+8e0fd85ee62b6791940ce32c220ca802a02f5e6f9d43a366f6d1f6b7bb53eb9a  build/TagLauncher.app/Contents/MacOS/TagLauncher
 ```
 
 ## Commands Run
diff --git a/Release/_archive/AppStore-7.6.0-20260525.0016/README.md b/Release/_archive/AppStore-7.6.0-20260525.0016/README.md
index 9b10aed..e728e9b 100644
--- a/Release/_archive/AppStore-7.6.0-20260525.0016/README.md
+++ b/Release/_archive/AppStore-7.6.0-20260525.0016/README.md
@@ -8,16 +8,16 @@
 - Platform: macOS / Mac App Store
 - Bundle ID: `com.taglauncher.app`
 - Version: `7.6.0`
-- Local QA build: `20260525.0016`
-- Frozen source commit: `0258b3e`
-- Frozen source branch: `main`
+- Local QA build: `20260529.0153` icon cleanup copy
+- Source ref: `codex/post-freeze-new-requirement` icon-resource hotfix
+- Source branch: `codex/post-freeze-new-requirement`
 - Release folder: `Release/AppStore-7.6.0-20260525.0016`
-- DMG SHA-256: `4689856f4a976c394ef4737db5bb5eebcc5b5bb95eea81fe72f5b6c3e3ed4b23`
-- App binary SHA-256: `01ace57df10061fd7d684fa8a5bd795f87f55ee2c713cbb1ab2d01f5f63ed404`
+- DMG SHA-256: `a887c26943136c629bf36a577ded512f85a0aac8132622e2c418c4c6d2b870f7`
+- App binary SHA-256: `8e0fd85ee62b6791940ce32c220ca802a02f5e6f9d43a366f6d1f6b7bb53eb9a`
 
 ## Freeze Status
 
-This release pack is frozen on the locally QA-passed build `20260525.0016`. Use this folder, its hashes, and its metadata as the source of truth for the first Mac App Store submission prep.
+This archive was originally frozen on the locally QA-passed build `20260525.0016`. On 2026-05-29 its local QA DMG and App icon asset were refreshed to remove stale icon packages from the project tree. This archive is reference-only and should not be used for submission.
 
 Do not use earlier prep folders or builds such as `20260524.1652` or `20260524.1849`; they predate the final fullscreen/Split View secondary-window close and same-app Split View fixes.
 
diff --git a/TODO.md b/TODO.md
index 5b1f981..3f1a784 100644
--- a/TODO.md
+++ b/TODO.md
@@ -38,6 +38,12 @@
 
 ## Done
 
+- [2026-05-29] 修复 App 图标白边并清除旧图标残留。
+  - 提交: 本次提交
+  - 结果: 当前 grid/rainbow AppIcon 的圆角外区域已改为透明;`generate_icon.py` 删除旧“两张标签”生成逻辑,并增加 grid/rainbow 图标族校验,防止旧图标被重新生成。
+  - 范围: 更新 `.icns`、`AppIcon.appiconset`、Release 1024 图标、Local QA DMG;`build.sh` 改为优先从 `AppIcon.appiconset` 生成 bundle `AppIcon.icns`。
+  - 验证: `python3 generate_icon.py`、`bash build.sh`、`codesign --verify --deep --strict`、DMG 挂载检查、全项目图片/DMG 旧图标近似匹配扫描均通过;根 `.icns`、appiconset、Release 1024 图标、bundle/DMG 内 AppIcon 四角 alpha 均为 0。
+
 - [2026-05-29] 清理或改名 `AppGridItem.swift` 残留。
   - 提交: 本次提交
   - 结果: `AppGridItem.swift` 已改名为 `AppGridSupport.swift`,文件标题改为 App Grid shared support,避免误解为旧 SwiftUI 浏览态 grid。
diff --git a/build.sh b/build.sh
index 3e68d0f..621d812 100644
--- a/build.sh
+++ b/build.sh
@@ -71,10 +71,39 @@
 /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $APP_BUILD" "$APP_INFO_PLIST"
 
 echo "==> Copying AppIcon.icns..."
-if [ -f "$PROJECT_DIR/icon-icns.icns" ]; then
+APPICON_SOURCE_DIR="$SWIFT_DIR/Assets.xcassets/AppIcon.appiconset"
+if [ -d "$APPICON_SOURCE_DIR" ]; then
+    TMP_ICONSET_PARENT="$(mktemp -d -t taglauncher-appicon.XXXXXX)"
+    TMP_ICONSET="$TMP_ICONSET_PARENT/AppIcon.iconset"
+    mkdir -p "$TMP_ICONSET"
+    ICON_NAMES=(
+        icon_16x16.png
+        icon_16x16@2x.png
+        icon_32x32.png
+        icon_32x32@2x.png
+        icon_128x128.png
+        icon_128x128@2x.png
+        icon_256x256.png
+        icon_256x256@2x.png
+        icon_512x512.png
+        icon_512x512@2x.png
+    )
+    for icon_name in "${ICON_NAMES[@]}"; do
+        if [ ! -f "$APPICON_SOURCE_DIR/$icon_name" ]; then
+            echo "❌ Missing AppIcon asset: $APPICON_SOURCE_DIR/$icon_name"
+            exit 1
+        fi
+        cp "$APPICON_SOURCE_DIR/$icon_name" "$TMP_ICONSET/$icon_name"
+    done
+    iconutil -c icns "$TMP_ICONSET" -o "$RESOURCES_DIR/AppIcon.icns"
+    rm -rf "$TMP_ICONSET_PARENT"
+elif [ -f "$PROJECT_DIR/icon-icns.icns" ]; then
     cp "$PROJECT_DIR/icon-icns.icns" "$RESOURCES_DIR/AppIcon.icns"
 elif [ -f "$SWIFT_DIR/AppIcon.iconset/icon_512x512@2x.png" ]; then
     iconutil -c icns "$SWIFT_DIR/AppIcon.iconset" -o "$RESOURCES_DIR/AppIcon.icns" 2>/dev/null
+else
+    echo "❌ Missing AppIcon source"
+    exit 1
 fi
 
 echo "==> Copying menu bar icon..."
diff --git a/generate_icon.py b/generate_icon.py
index 8331fc9..88393fb 100644
--- a/generate_icon.py
+++ b/generate_icon.py
@@ -1,109 +1,183 @@
 #!/usr/bin/env python3
-"""Generate TagLauncher app icon — two overlapping tags (red + blue) on macOS squircle."""
-from PIL import Image, ImageDraw, ImageFilter
-import math, os, subprocess, tempfile
+"""Regenerate the current TagLauncher grid/rainbow app icon assets."""
+
+from __future__ import annotations
+
+import colorsys
+import subprocess
+import tempfile
+from pathlib import Path
+
+from PIL import Image, ImageChops, ImageDraw
+
 
 SIZE = 1024
-PROJECT_DIR = os.path.dirname(os.path.abspath(__file__))
+PROJECT_DIR = Path(__file__).resolve().parent
+APPICON_DIR = PROJECT_DIR / "Apptag" / "Assets.xcassets" / "AppIcon.appiconset"
+ROOT_ICNS = PROJECT_DIR / "icon-icns.icns"
 
-def rounded_rectangle_mask(size, radius):
-    mask = Image.new("L", (size, size), 0)
+RELEASE_ICON_TARGETS = [
+    PROJECT_DIR
+    / "Release"
+    / "AppStore-7.6.0-20260527.0124"
+    / "Assets"
+    / "TagLauncher-AppIcon-1024.png",
+    PROJECT_DIR
+    / "Release"
+    / "_archive"
+    / "AppStore-7.6.0-20260525.0016"
+    / "Assets"
+    / "TagLauncher-AppIcon-1024.png",
+]
+
+SOURCE_CANDIDATES = [
+    APPICON_DIR / "icon_512x512@2x.png",
+    RELEASE_ICON_TARGETS[0],
+    ROOT_ICNS,
+]
+
+VARIANTS = [
+    ("icon_16x16.png", 16),
+    ("icon_16x16@2x.png", 32),
+    ("icon_32x32.png", 32),
+    ("icon_32x32@2x.png", 64),
+    ("icon_128x128.png", 128),
+    ("icon_128x128@2x.png", 256),
+    ("icon_256x256.png", 256),
+    ("icon_256x256@2x.png", 512),
+    ("icon_512x512.png", 512),
+    ("icon_512x512@2x.png", 1024),
+]
+
+# The approved grid/rainbow icon artwork sits inside this rounded rect.
+# Keeping this mask explicit prevents the old opaque-white square corners from
+# reappearing when assets are regenerated from an older flattened source.
+MASK_BOUNDS = (77, 57, 943, 934)
+MASK_RADIUS = 232
+
+
+def load_source() -> tuple[Path, Image.Image]:
+    for path in SOURCE_CANDIDATES:
+        if not path.exists():
+            continue
+        with Image.open(path) as image:
+            image.load()
+            source = image.convert("RGBA").resize((SIZE, SIZE), Image.LANCZOS)
+        return path, source
+    raise FileNotFoundError("No app icon source found.")
+
+
+def assert_current_grid_rainbow_icon(image: Image.Image) -> None:
+    """Reject the removed two-tag icon if it is accidentally used as source."""
+
+    bands = {"yellow": 0, "green": 0, "cyan": 0, "purple": 0}
+    pixels = image.load()
+
+    for y in range(120, 900, 4):
+        for x in range(520, 900, 4):
+            red, green, blue, alpha = pixels[x, y]
+            if alpha < 128:
+                continue
+            hue, saturation, value = colorsys.rgb_to_hsv(
+                red / 255.0, green / 255.0, blue / 255.0
+            )
+            if saturation < 0.30 or value < 0.35:
+                continue
+            if 0.10 <= hue <= 0.19:
+                bands["yellow"] += 1
+            elif 0.20 <= hue <= 0.42:
+                bands["green"] += 1
+            elif 0.43 <= hue <= 0.58:
+                bands["cyan"] += 1
+            elif 0.70 <= hue <= 0.86:
+                bands["purple"] += 1
+
+    present_bands = [name for name, count in bands.items() if count >= 100]
+    if len(present_bands) < 3:
+        raise ValueError(
+            "Source image does not match the current grid/rainbow icon family; "
+            f"detected color bands: {bands}"
+        )
+
+
+def icon_mask() -> Image.Image:
+    x0, y0, x1, y1 = MASK_BOUNDS
+    mask = Image.new("L", (SIZE, SIZE), 0)
     draw = ImageDraw.Draw(mask)
-    draw.rounded_rectangle([(0, 0), (size-1, size-1)], radius=radius, fill=255)
+    draw.rounded_rectangle(
+        [x0, y0, x1 - 1, y1 - 1],
+        radius=MASK_RADIUS,
+        fill=255,
+    )
     return mask
 
-def draw_tag(cx, cy, width, height, color, angle_deg, hole_ratio=0.22):
-    padding = int(width * 1.5)
-    tag_img = Image.new("RGBA", (padding*2, padding*2), (0,0,0,0))
-    tag_draw = ImageDraw.Draw(tag_img)
-    x0 = padding - width//2
-    y0 = padding - height//2
-    x1 = padding + width//2
-    y1 = padding + height//2
-    r = int(min(width, height) * 0.18)
-    tag_draw.rounded_rectangle([x0, y0, x1, y1], radius=r, fill=color)
-    hole_r = int(width * hole_ratio)
-    hole_x = padding + width//2 - int(width * 0.22)
-    hole_y = padding - height//2 + int(height * 0.2)
-    tag_draw.ellipse(
-        [hole_x - hole_r, hole_y - hole_r, hole_x + hole_r, hole_y + hole_r],
-        fill=(0,0,0,0)
-    )
-    tag_img = tag_img.rotate(angle_deg, resample=Image.BICUBIC, expand=True)
-    return tag_img
 
-# --- Build the icon ---
-img = Image.new("RGBA", (SIZE, SIZE), (0,0,0,0))
+def normalize_icon(image: Image.Image) -> Image.Image:
+    image = image.resize((SIZE, SIZE), Image.LANCZOS).convert("RGBA")
+    alpha = ImageChops.multiply(image.getchannel("A"), icon_mask())
+    normalized = Image.new("RGBA", (SIZE, SIZE), (0, 0, 0, 0))
+    normalized.paste(image, (0, 0), alpha)
+    normalized.putalpha(alpha)
+    return normalized
 
-squircle_r = int(SIZE * 0.225)
-bg_mask = rounded_rectangle_mask(SIZE, squircle_r)
-bg_color = Image.new("RGBA", (SIZE, SIZE), (240, 241, 245, 255))
-img = Image.composite(bg_color, img, bg_mask)
 
-red_color = (220, 45, 85, 255)
-blue_color = (45, 130, 220, 255)
+def save_png(path: Path, image: Image.Image, size: int) -> None:
+    path.parent.mkdir(parents=True, exist_ok=True)
+    resized = image.resize((size, size), Image.LANCZOS)
+    resized.save(path, "PNG", optimize=True)
+    print(f"  {path.relative_to(PROJECT_DIR)} ({size}x{size})")
 
-tag_w = int(SIZE * 0.42)
-tag_h = int(SIZE * 0.55)
-red_tag = draw_tag(0, 0, tag_w, tag_h, red_color, -8)
-red_x = SIZE//2 - red_tag.width//2
-red_y = SIZE//2 - red_tag.height//2 - int(SIZE * 0.04)
 
-tag_w2 = int(SIZE * 0.46)
-tag_h2 = int(SIZE * 0.58)
-blue_tag = draw_tag(0, 0, tag_w2, tag_h2, blue_color, 12)
-blue_x = SIZE//2 - blue_tag.width//2 + int(SIZE * 0.02)
-blue_y = SIZE//2 - blue_tag.height//2 + int(SIZE * 0.03)
+def generate_icns(image: Image.Image) -> None:
+    with tempfile.TemporaryDirectory() as temp_dir:
+        iconset = Path(temp_dir) / "AppIcon.iconset"
+        iconset.mkdir()
+        for name, size in VARIANTS:
+            image.resize((size, size), Image.LANCZOS).save(iconset / name, "PNG")
+        subprocess.run(
+            ["iconutil", "-c", "icns", str(iconset), "-o", str(ROOT_ICNS)],
+            check=True,
+        )
+    print(f"  {ROOT_ICNS.relative_to(PROJECT_DIR)}")
 
-# Drop shadows
-shadow = blue_tag.copy()
-shadow_data = shadow.getdata()
-shadow.putdata([(0,0,0, min(a//4, 80)) if a > 0 else (0,0,0,0) for (r,g,b,a) in shadow_data])
-shadow = shadow.filter(ImageFilter.GaussianBlur(radius=SIZE*0.025))
-img.paste(shadow, (blue_x+int(SIZE*0.015), blue_y+int(SIZE*0.02)), shadow)
-img.paste(blue_tag, (blue_x, blue_y), blue_tag)
 
-shadow2 = red_tag.copy()
-shadow_data2 = shadow2.getdata()
-shadow2.putdata([(0,0,0, min(a//3, 80)) if a > 0 else (0,0,0,0) for (r,g,b,a) in shadow_data2])
-shadow2 = shadow2.filter(ImageFilter.GaussianBlur(radius=SIZE*0.02))
-img.paste(shadow2, (red_x+int(SIZE*0.01), red_y+int(SIZE*0.015)), shadow2)
-img.paste(red_tag, (red_x, red_y), red_tag)
+def print_corner_alpha(path: Path) -> None:
+    with Image.open(path) as image:
+        rgba = image.convert("RGBA")
+        width, height = rgba.size
+        corners = [
+            rgba.getpixel((0, 0))[3],
+            rgba.getpixel((width - 1, 0))[3],
+            rgba.getpixel((0, height - 1))[3],
+            rgba.getpixel((width - 1, height - 1))[3],
+        ]
+    print(f"  alpha corners {path.relative_to(PROJECT_DIR)}: {corners}")
 
-mask = rounded_rectangle_mask(SIZE, squircle_r)
-img.putalpha(mask)
 
-# --- Save PNG variants to temp .iconset, then generate .icns ---
-with tempfile.TemporaryDirectory() as tmpdir:
-    iconset = os.path.join(tmpdir, "AppIcon.iconset")
-    os.makedirs(iconset)
+def main() -> None:
+    source_path, source = load_source()
+    assert_current_grid_rainbow_icon(source)
+    icon = normalize_icon(source)
 
-    variants = [
-        ("icon_16x16.png", 16),
-        ("icon_16x16@2x.png", 32),
-        ("icon_32x32.png", 32),
-        ("icon_32x32@2x.png", 64),
-        ("icon_128x128.png", 128),
-        ("icon_128x128@2x.png", 256),
-        ("icon_256x256.png", 256),
-        ("icon_256x256@2x.png", 512),
-        ("icon_512x512.png", 512),
-        ("icon_512x512@2x.png", 1024),
-    ]
+    print(f"Source: {source_path.relative_to(PROJECT_DIR)}")
+    print("Writing AppIcon.appiconset:")
+    save_png(APPICON_DIR / "icon_1024_preview.png", icon, 1024)
+    for name, size in VARIANTS:
+        save_png(APPICON_DIR / name, icon, size)
 
-    for name, size in variants:
-        resized = img.resize((size, size), Image.LANCZOS)
-        path = os.path.join(iconset, name)
-        resized.save(path, "PNG", optimize=True)
-        print(f"  {name} ({size}x{size}): {os.path.getsize(path):,}B")
+    print("Writing release 1024 assets:")
+    for target in RELEASE_ICON_TARGETS:
+        save_png(target, icon, 1024)
 
-    # Generate .icns to project root
-    out_icns = os.path.join(PROJECT_DIR, "icon-icns.icns")
-    subprocess.run(["iconutil", "-c", "icns", iconset, "-o", out_icns], check=True)
-    icns_size = os.path.getsize(out_icns)
-    print(f"\nGenerated: {out_icns} ({icns_size:,}B, {icns_size/1024:.0f}KB)")
+    print("Writing root .icns:")
+    generate_icns(icon)
 
-# Also save 1024x1024 preview
-preview_path = os.path.join(PROJECT_DIR, "icon_preview.png")
-img.save(preview_path, "PNG", optimize=True)
-print(f"Preview: {preview_path}")
+    print("Validation:")
+    print_corner_alpha(ROOT_ICNS)
+    print_corner_alpha(APPICON_DIR / "icon_512x512@2x.png")
+    for target in RELEASE_ICON_TARGETS:
+        print_corner_alpha(target)
+
+
+if __name__ == "__main__":
+    main()
diff --git a/icon-icns.icns b/icon-icns.icns
index 6e114cd..99e2197 100644
--- a/icon-icns.icns
+++ b/icon-icns.icns
Binary files differ

--
Gitblit v1.9.3