From f474c8a6fdbb18f53f4b65155facbe89f5c95ed8 Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Mon, 08 Jun 2026 23:59:09 +0800
Subject: [PATCH] Release 7.8.23 App Grid hover stability

---
 AGENTS.md                    |    8 ++
 src/CHANGELOG.md             |    7 +
 src/TODO.md                  |    5 +
 CODE_GOVERNANCE.md           |  176 ++++++++++++++++++++++++++++++++++++++++++++
 src/Apptag/Info.plist        |    4 
 src/Apptag/ContentView.swift |   17 ----
 6 files changed, 198 insertions(+), 19 deletions(-)

diff --git a/AGENTS.md b/AGENTS.md
index e2b8026..6d52102 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -7,6 +7,14 @@
 
 这是 AI Agent 进入 `/Users/ar/Projects/Taglauncher` 后应先读的入口文件。
 
+## 代码治理入口
+
+开始任何代码、Git、迁移、构建、发布或 QA 工作前,必须读取并遵守:
+
+`/Users/ar/Projects/Taglauncher/CODE_GOVERNANCE.md`
+
+本入口文件只保留高优先级硬约束;完整执行标准以 `CODE_GOVERNANCE.md` 为准。若两者冲突,以更严格、项目本地、更具体的规则为准。
+
 ## 源码根目录
 
 唯一源码根目录:`/Users/ar/Projects/Taglauncher/src`
diff --git a/CODE_GOVERNANCE.md b/CODE_GOVERNANCE.md
new file mode 100644
index 0000000..623718f
--- /dev/null
+++ b/CODE_GOVERNANCE.md
@@ -0,0 +1,176 @@
+# Taglauncher 代码治理与 Git 规范
+
+本文档是 `/Users/ar/Projects/Taglauncher` 的代码管理、Git 使用、交付和 Agent 协作规范。根目录 `AGENTS.md` 是强制入口;本文件是完整执行标准。
+
+## 1. 项目边界
+
+- 主仓库工作区固定为 `/Users/ar/Projects/Taglauncher`。
+- 唯一源码根目录固定为 `/Users/ar/Projects/Taglauncher/src`。
+- App 源码、构建脚本、QA 脚本、SmartStart/Apple catalog 资料、发布资料都必须在 `src/` 下维护。
+- 项目根目录只保留仓库入口文档、公开网站资料、治理规范和非源码管理说明。
+- 不允许再创建或继续使用 `/Users/ar/Projects/Taglauncher-*source`、`/Users/ar/Projects/Apptag-*` 等外部源码目录。
+
+## 2. Git 工作区规则
+
+- 开始任何代码、文档、发布或迁移任务前,必须先执行并检查:
+
+```bash
+git status --short 2>&1 | head -c 6000
+git branch --show-current 2>&1 | head -c 2000
+git worktree list --porcelain 2>&1 | head -c 6000
+```
+
+- 如果工作区已有改动,必须区分改动来源:
+  - 用户或其他 Agent 的改动不得擅自回滚。
+  - 与当前任务无关的改动保持原样。
+  - 与当前任务相关但来源不明的改动,先读懂再继续。
+- 禁止使用 `git reset --hard`、`git checkout --`、`git clean` 等破坏性命令,除非用户明确要求并确认目标。
+
+## 3. 分支策略
+
+- `main` 是主线,不在脏工作区中直接做实验。
+- 研发、迁移、修复、发布准备应使用独立分支。
+- Agent 创建分支默认使用 `codex/` 前缀,例如:
+
+```bash
+git switch -c codex/fix-quick-search-index
+git switch -c codex/relocate-source-to-src
+```
+
+- 不允许用外部源码目录代替正常 Git branch。
+- 大规模重构、历史迁移、发布冻结前,必须先确认当前分支、HEAD 和安全固定点。
+
+## 4. Commit 规则
+
+- 每个 commit 应表达一个明确意图,不把无关改动混在一起。
+- 提交前必须确认:
+
+```bash
+git status --short 2>&1 | head -c 6000
+git diff --stat 2>&1 | head -c 6000
+git diff --cached --stat 2>&1 | head -c 6000
+```
+
+- 提交信息使用简洁英文或项目已有风格,示例:
+  - `Fix quick search system app matching`
+  - `Release 7.8.22 Apple default app catalog`
+  - `Relocate app source under src`
+- 代码行为、构建、发布资料或用户可见改动提交前必须完成对应 QA,并记录结果。
+- 不允许为了“看起来干净”而提交未解释的临时产物、缓存、用户本地数据或证书。
+
+## 5. Tag 与发布固定点
+
+- 发布、分发、安装包、App Store 上传、迁移历史前,必须建立可回退固定点。
+- 发布 tag 必须包含版本和 build,例如:
+
+```bash
+git tag -a v7.8.22-build20260608.1324 -m "Release 7.8.22 build 20260608.1324"
+```
+
+- 迁移或高风险操作前建议建立 `pre-*` 安全 tag,例如:
+
+```bash
+git tag -a pre-src-migration-main-YYYYMMDD.HHMM -m "Pre src migration main"
+```
+
+- tag、`Info.plist`、`CHANGELOG.md`、`Release/` 资料、最终安装包文件名和 build 编号必须一致。
+
+## 6. Worktree 使用规则
+
+- 默认不使用 worktree;需要并行工作时优先使用当前仓库的正常 branch。
+- 如确需 worktree,必须先说明:
+  - 目的。
+  - 路径。
+  - 对应分支。
+  - 预计生命周期。
+  - 清理条件。
+- worktree 不得放在 `/Users/ar/Projects/Taglauncher-*source` 或 `/Users/ar/Projects/Apptag-*` 这类容易被误认为正式源码根目录的位置。
+- 任务完成后必须执行:
+
+```bash
+git worktree remove WORKTREE_PATH 2>&1 | head -c 6000
+git worktree prune 2>&1 | head -c 6000
+git worktree list --porcelain 2>&1 | head -c 6000
+```
+
+- 如果 worktree 有未提交改动,禁止直接删除;必须先确认归属和处理方式。
+
+## 7. 构建产物与敏感文件
+
+- `build/`、临时安装包、编译缓存、用户本地数据、钥匙串资料、p12 证书、provisioning profile 默认不进源码提交。
+- 只有明确作为 release archive 的产物,才可放入 `src/Release/.../Archive/`,并必须配套说明、hash、版本和 QA 证据。
+- 证书目录只作为本地敏感资料管理,不作为源码迁移内容。
+- 不允许把真实用户数据、隐私资料、账号凭证或本地配置写入 Git。
+
+## 8. Agent 接手流程
+
+接手旧线程、长期任务、发布任务或迁移任务时,必须先完成以下检查,不得等待旧线程:
+
+```bash
+git status --short 2>&1 | head -c 6000
+git branch --show-current 2>&1 | head -c 2000
+git log --oneline --decorate --graph --max-count=12 2>&1 | head -c 6000
+git worktree list --porcelain 2>&1 | head -c 6000
+```
+
+- 必须读取最近会话记录,确认未完成项、已完成项、阻塞项和用户最新指令。
+- 必须确认当前工作区是否处于 merge、rebase、cherry-pick 或 no-commit 状态。
+- 不得因为旧线程在等待而继续等待;如果当前上下文足够,应直接推进。
+- 如果必须等待用户,必须明确说明等待原因、需要用户做什么、收到回复后的下一步。
+
+## 9. QA 与交付门禁
+
+- 开发完成不能直接交付,必须先自查和验证。
+- 小改动至少运行与改动直接相关的 QA。
+- 影响 App 行为、构建脚本、发布资料或用户可见功能时,至少确认:
+  - 代码 diff 范围。
+  - 相关 QA 结果。
+  - 构建是否通过。
+  - 是否产生额外未跟踪文件。
+- 迁移、发布、构建任务必须记录可复核证据:版本/build、执行命令、关键结果、产物路径、hash 或 QA 报告。
+- QA 失败不能只口头解释;必须判断是产品回归、脚本断言问题、环境问题还是迁移无关问题,并记录结论。
+
+## 10. 命令输出保护
+
+任何未知或可能很大的命令输出都必须 byte-cap:
+
+```bash
+COMMAND 2>&1 | head -c 6000
+```
+
+- 构建、测试、目录遍历、日志、Git diff、搜索结果都应限制输出。
+- 搜索优先用 `rg` / `rg --files`。
+- 不无上限打印大文件、构建日志、目录树或二进制信息。
+
+## 11. 禁止事项
+
+- 禁止在 `src/` 外新增 App 源码副本。
+- 禁止用外部目录长期承载源码开发。
+- 禁止在不看 `git status` 的情况下提交、合并、发布或清理。
+- 禁止擅自回滚用户改动。
+- 禁止把证书、账号、用户数据、临时 build 缓存提交进 Git。
+- 禁止把阶段性通过当成整体完成;仍有明确未完成项时必须继续推进。
+- 禁止没有 QA 证据就声称可交付。
+
+## 12. 常用检查命令
+
+```bash
+git status --short 2>&1 | head -c 6000
+git branch --show-current 2>&1 | head -c 2000
+git log --oneline --decorate --graph --max-count=12 2>&1 | head -c 6000
+git worktree list --porcelain 2>&1 | head -c 6000
+git diff --stat 2>&1 | head -c 6000
+git diff --cached --stat 2>&1 | head -c 6000
+git ls-files src 2>&1 | wc -l | head -c 2000
+```
+
+从源码根目录运行 QA:
+
+```bash
+cd /Users/ar/Projects/Taglauncher/src
+bash Scripts/apple_default_apps_resource_qa.sh 2>&1 | head -c 12000
+bash Scripts/apple_default_note_policy_qa.sh 2>&1 | head -c 12000
+bash Scripts/smartstart_catalog_resource_qa.sh 2>&1 | head -c 12000
+bash Scripts/quick_search_app_name_qa.sh 2>&1 | head -c 12000
+bash Scripts/quick_search_system_app_qa.sh 2>&1 | head -c 12000
+```
diff --git a/src/Apptag/ContentView.swift b/src/Apptag/ContentView.swift
index e2bf1c7..a6011b8 100644
--- a/src/Apptag/ContentView.swift
+++ b/src/Apptag/ContentView.swift
@@ -319,8 +319,6 @@
     var bubbleDraftNote = ""
     var tagNavigationHoveredGroupName: String? = nil
     var tagNavigationAppDropTargetName: String? = nil
-    var tagNavigationLastHoverScrollID: String? = nil
-    var tagNavigationLastHoverScrollAt: Date? = nil
 }
 
 private struct EditActionFeedback: Identifiable {
@@ -432,8 +430,6 @@
             ?? (isColorlessContainerMode ? filledColorlessContainer : nil)
     }
     private let rightSidebarFloatingClearance: CGFloat = 44
-    private let tagNavigationHoverScrollInterval: TimeInterval = 0.22
-
     private var floatingButtonSurfaceColor: Color {
         colorScheme == .dark
             ? Color.white.opacity(0.10)
@@ -2001,7 +1997,6 @@
 
         appGridInteraction.tagNavigationHoveredGroupName = id
         fillColorlessContainer(id)
-        scrollToTagFromHover(id)
     }
 
     private func handleTagNavigationAppDropHover(_ id: String, active: Bool) {
@@ -2020,18 +2015,6 @@
         }
 
         appGridInteraction.tagNavigationAppDropTargetName = id
-    }
-
-    private func scrollToTagFromHover(_ id: String) {
-        let now = Date()
-        if appGridInteraction.tagNavigationLastHoverScrollID == id,
-           let lastScrollAt = appGridInteraction.tagNavigationLastHoverScrollAt,
-           now.timeIntervalSince(lastScrollAt) < tagNavigationHoverScrollInterval {
-            return
-        }
-        appGridInteraction.tagNavigationLastHoverScrollID = id
-        appGridInteraction.tagNavigationLastHoverScrollAt = now
-        scrollTo(id)
     }
 
     private func fillColorlessContainer(_ id: String) {
diff --git a/src/Apptag/Info.plist b/src/Apptag/Info.plist
index d59a6b0..f503558 100644
--- a/src/Apptag/Info.plist
+++ b/src/Apptag/Info.plist
@@ -19,9 +19,9 @@
 	<key>CFBundlePackageType</key>
 	<string>APPL</string>
 	<key>CFBundleShortVersionString</key>
-	<string>7.8.22</string>
+	<string>7.8.23</string>
 	<key>CFBundleVersion</key>
-	<string>20260608.1324</string>
+	<string>20260608.2356</string>
 	<key>LSApplicationCategoryType</key>
 	<string>public.app-category.utilities</string>
 	<key>LSMinimumSystemVersion</key>
diff --git a/src/CHANGELOG.md b/src/CHANGELOG.md
index e3290b0..99e6502 100644
--- a/src/CHANGELOG.md
+++ b/src/CHANGELOG.md
@@ -1,5 +1,12 @@
 # TagLauncher Changelog
 
+## [7.8.23] — 2026-06-08
+
+- 收敛 App Grid 顶部/侧边 tag hover 交互:鼠标悬停 tag 只保留高亮/填色,不再自动滚动到分组,避免 hover 与内容滚动互相触发造成可感知抖动
+- 点击 tag 仍会滚动到对应分组,保留原有显式导航语义
+- 新增项目代码治理入口文档,明确唯一源码根目录、Git/QA/发布冻结与构建产物规则
+- 版本号更新为 `7.8.23`,Build 更新为 `20260608.2356`
+
 ## [7.8.22] — 2026-06-08
 
 - 补齐 Apple 默认应用 catalog 对 `/System/Library/CoreServices/Applications` 的覆盖:钥匙串访问、归档实用工具、扩充槽实用工具、反馈助理、无线诊断等系统内置工具现在都有默认名称和备注
diff --git a/src/TODO.md b/src/TODO.md
index 1132d25..16c985e 100644
--- a/src/TODO.md
+++ b/src/TODO.md
@@ -23,6 +23,11 @@
 
 ## Done
 
+- [2026-06-08] 修复 App Grid 顶部 tag hover 触发自动滚动导致的抖动。
+  - 结果: hover 只保留 tag 高亮/填色,不再自动滚动;点击 tag 仍滚动到对应分组。
+  - 范围: 只改 `Apptag/ContentView.swift` 的 tag hover 处理,不改 App Grid 布局算法、不改拖拽、不改点击导航语义。
+  - 验证: `bash build.sh` 和 `codesign --verify --deep --strict build/TagLauncher.app` 通过;用户使用新版后确认仍有轻微小抖,但效果可接受,本轮不继续扩大修复范围。
+
 - [2026-06-04] 修复新安装 App 后 App Grid / Quick Search 不能立即检索到的问题。
   - 提交: 本次提交
   - 结果: App Grid / Quick Search 打开时先轻量检查标准应用目录签名;签名未变化时不刷新也不重建界面,目录变化时才后台重扫应用索引。

--
Gitblit v1.9.3