Ariver
2026-08-30 ec338c687e2e04bd37ab5c76a0a9c19769190502
CODEGRAPH.md
@@ -1,53 +1,55 @@
# TagLauncher CODEGRAPH
最后更新:2026-07-01
最后更新:2026-07-07
用途:本文件是 TagLauncher 的长期工程地图。修改用户可见行为、状态模型、构建/发布入口、核心源码或 QA 入口前,应先读本文件,再读指向的真实源码。若本文件与源码不一致,以源码为准,并在同一任务内更新本文件。
## 项目边界
- 仓库根目录:`/Users/ar/Projects/Taglauncher`
- 唯一源码根目录:`/Users/ar/Projects/Taglauncher/src`
- macOS App 源码:`src/Apptag/`
- 构建入口:`src/build.sh`
- DMG 打包入口:`src/make_dmg.sh`
- 发布资料:`src/Release/`
- QA 脚本:`src/Scripts/`
- 仓库根目录:`/Users/ar/Projects/Taglauncher/03-O`
- 唯一源码根目录:`/Users/ar/Projects/Taglauncher/03-O/C1.source`
- macOS App 源码:`C1.source/Apptag/`
- 构建入口:`C1.source/build.sh`
- DMG 打包入口:`C1.source/make_dmg.sh`
- 发布资料:`K3.运营与发布资料/Release/`
- 当前迁入构建包:`C2.builds/`
- QA 脚本:`C1.source/Scripts/`
## 核心入口
- `src/Apptag/ApptagApp.swift`
- `C1.source/Apptag/ApptagApp.swift`
  - `TagLauncherApp`:SwiftUI App 入口。
  - `AppDelegate`:菜单栏状态项、Dock 显示策略、热键注册、窗口打开、Quick Search 触发、App 生命周期。
  - 支持外部 URL 唤起 `taglauncher://show`:只做 AppGrid show/focus,不做 toggle;冷启动时请求会排队到初始化完成后执行;不接管原生触控板手势。
  - 支持从标签导航双击进入设置页的 Tags tab。
  - 启动时初始化 `ProEntitlementCenter`,保证免费 / Pro / 老用户自动 Pro 状态进入全局同步快照。
  - 菜单栏下拉菜单包含免费 / Pro 当前身份状态项;免费状态文案引导立刻升级到 `👑Pro`,点击进入 Pro 设置页,Pro 状态使用金色皇冠图标。
- `src/Apptag/OverlayWindowController.swift`
- `C1.source/Apptag/OverlayWindowController.swift`
  - `OverlayPanel` / `OverlayWindowController`:AppGrid 浮层窗口与显示/隐藏控制。
- `src/Apptag/ContentView.swift`
- `C1.source/Apptag/ContentView.swift`
  - `ContentView`:AppGrid 主界面、标签导航、编辑模式、拖拽处理、Quick Search 数据刷新、使用技巧浮层入口。
  - 读取 `appGridThemeID` 和炫彩主题调色值,并负责 AppGrid 全屏主题背景渲染。
  - 编辑模式加载 `TagDef.customColor` 并传入 AppGrid、标签导航和标签编辑器;标签显示优先使用自定义颜色,缺省回退基础色。
  - 编辑模式使用 runtime theme override:任何主题下进入编辑都临时显示默认浅色毛玻璃。
  - 使用最近一次完整 `AppLibrarySnapshot` 先渲染 AppGrid,再后台刷新,避免启动/重开时立刻显示转圈。
  - 使用技巧关闭提醒由 `ContentView` 统一弹 modal 并写入 `hideUsageTips` / `skipUsageTipsCloseReminder`。
  - Quick Search 标签筛选状态只存在于当前面板生命周期;`ContentView` 从当前索引和 `tagDefinitions` 生成可选真实标签,并通过 `AppContainerID.isReservedGroupName` 排除未分类 / Mac 自带 / 不常用等保护容器名,打开、关闭、初始 Quick Search、标签删除/重命名或刷新后失效时都清空筛选。
  - Quick Search 点击 TagLauncher 自身结果时只关闭当前浮层,不走外部自启动,避免 AppGrid 被重新拉起。
- `src/Apptag/PreferencesView.swift`
- `C1.source/Apptag/PreferencesView.swift`
  - `PreferencesView`:设置窗口、语言、通用、主题、快捷键、标签、数据、Pro、关于等设置页。
  - 顶部设置页签必须保持 8 个标签总宽不超过旧 7 标签宽度;图标统一使用线型 SF Symbols,`Pro` 页签位于数据之后、关于之前,使用线型皇冠。
  - 设置页签下方按页签渲染统一固定位置的 `settingsFixedProHeader`:语言 / 通用 / 主题 / 快捷键 / 标签 / 数据 / Pro / 关于 8 个页签都显示该行且位置不漂移。免费态左侧状态用“当前免费版用户”完整句而不是“免费版”胶囊;通用 / 主题 / 快捷键 / 标签 / 数据页显示当前 tab 对应购买引导和解锁/恢复按钮,语言和关于页只显示状态与操作按钮,不显示购买说明文字;已解锁 Pro 时,语言 / Pro / 关于页统一居中显示 `Pro 已解锁` 胶囊加 `settings.proStatus.proUser` 文案,不显示恢复购买按钮,且 `settings.proStatus.proUser` 本地化文字不再内置皇冠图标。
  - 设置页签下方按页签渲染统一固定位置的 `settingsFixedProHeader`:语言 / 通用 / 主题 / 快捷键 / 标签 / 数据 / Pro / 关于 8 个页签都显示该行且位置不漂移。免费态左侧状态用“当前免费版用户”完整句而不是“免费版”胶囊;通用 / 主题 / 快捷键 / 标签 / 数据页显示当前 tab 对应购买引导和解锁/恢复按钮,语言和关于页只显示状态与操作按钮,不显示购买说明文字;已解锁 Pro 时,语言 / Pro / 关于页统一居中显示 `Pro 已解锁` 胶囊加 `settings.proStatus.proUser` 文案,不显示恢复购买按钮,且 `settings.proStatus.proUser` 本地化文字不再内置皇冠图标。8.3.6 起该固定行不渲染包住整行的外层圆角矩形背景或描边。
  - Pro 专属主题、彩色容器 / 彩色网格、自定义快捷键、自定义标签颜色和数据导入导出入口即使已解锁,也应保留皇冠 Pro 标识。
  - Language tab 去掉重复标题说明,语言矩阵在主内容区域上下左右居中;About tab 应用信息块也在主内容区域居中。
  - Theme tab 只写视觉偏好 `appGridThemeID` 和炫彩主题调色值,炫彩滑轨只能影响 AppGrid 背景,不得改变标签、排序、备注或分类数据。
  - 免费用户预览 Pro 主题时,Theme tab 状态行和当前预览主题卡片显示基于 `ProThemePreviewState.endsAt` 推导的 `MM:SS` 倒计时;倒计时到期只退出预览,不弹阻塞提示。
  - Pro tab 展示免费版 / Pro 版对比表;对比表不显示独立标题,Pro 列标题前必须有线型皇冠标识。
  - Pro tab 对比表包含自定义标签颜色、彩色容器 / 彩色网格、高级主题、自定义快捷键、自定义应用备注和数据导入导出 / 分类与布局备份恢复;免费列锁定功能显示“不可用”,彩色容器 / 彩色网格和高级主题显示“只可预览 5 分钟”,备注显示“免费 3 个”;Pro 列未购买时显示带勾的“支持”,备注行显示带勾的“无限备注”,已购买后功能行显示带勾的“已解锁”。表格内免费列和 Pro 列的表头及状态胶囊都在列内左对齐;所有状态胶囊使用与“免费 3 个”一致的中性样式,不显示皇冠图标或黄色 Pro 背景。
  - Pro tab 对比表包含可维护标签数量、容器内 App 图标位置排序、自定义标签颜色、彩色容器 / 彩色网格、高级主题、自定义快捷键、自定义应用备注和数据导入导出 / 分类与布局备份恢复;标签列表自身顺序不列入 Pro 对比,因为免费用户也可持久保存。免费列锁定功能显示“不可用”,彩色容器 / 彩色网格和高级主题显示“只可预览 5 分钟”,备注显示“免费 3 个”;Pro 列未购买时显示带勾的“支持”,备注行显示带勾的“无限备注”,已购买后功能行显示带勾的“已解锁”。表格内免费列和 Pro 列的表头及状态胶囊都在列内左对齐;所有状态胶囊使用与“免费 3 个”一致的中性样式,不显示皇冠图标或黄色 Pro 背景。
  - About tab 保留顶部固定 Pro 状态行;主内容只保留应用信息、帮助文档和联系信息,不放 Pro 汇总卡或免费 / Pro 差异表。
## AppGrid 显示与交互
- `src/Apptag/AppGridCollectionView.swift`
- `C1.source/Apptag/AppGridCollectionView.swift`
  - `AppGridCollectionView`:SwiftUI 到 AppKit `NSCollectionView` 的桥接。
  - `AppGridCollectionHostView`:滚动容器、背景/使用技巧层、空白拖放处理。
  - `AppGridGroupCollectionItem` / `AppGridGroupCardView`:分组容器、图标布局、分组标题、hover/高亮、容器内拖放。
@@ -56,43 +58,43 @@
  - 不拥有 AppGrid 全屏渐变背景,只接收 theme 推导出的玻璃和文本可读性 token。
  - 分组标题颜色从 `TagDef.customColor` 优先解析;custom color signature 参与刷新签名,避免颜色变更后 AppGrid 不刷新。
  - 样式 2 / 样式 3 的瀑布流容器布局会把未分类和 Mac 自带作为底部特殊容器:未分类倒数第二、Mac 自带最后,二者横向占满;普通列末尾会补齐到特殊容器上沿,避免底部参差空隙。
- `src/Apptag/AppGridTheme.swift`
- `C1.source/Apptag/AppGridTheme.swift`
  - AppGrid 主题事实源:theme id、localization key、设置页 swatch、全屏渐变背景、炫彩主题调色板、玻璃明暗、编辑模式 token。
  - 持久化 key:`appGridThemeID`;暗色 / 亮色炫彩额外使用各自的调色值 key。
  - 主题是否需要 Pro 只通过 `ProEntitlementConfig.freeThemes` 判断,不在主题 UI 中散落规则。
- `src/Apptag/ProEntitlement.swift`
- `C1.source/Apptag/ProEntitlement.swift`
  - `ProEntitlementCenter`:StoreKit 2 当前权益、购买、恢复、交易更新、离线缓存和 QA 状态注入。
  - `ProEntitlementPolicy`:数据层可同步调用的 Pro 门禁;覆盖主题、彩色容器 / 彩色网格显示模式、导入 / 导出、备注额度、自定义标签颜色、自定义快捷键和应用排序持久化。
  - `ProEntitlementConfig`:一次性买断商品 ID、免费 + Pro 首个版本、免费主题集合、免费 3 条备注额度和 QA 环境变量的单一配置点。
  - `ProThemePreviewState` 可携带临时炫彩调色值;免费预览期间只写全局快照,不写真实 `UserDefaults`。
  - `ProDisplayModePreviewState` 复用 Pro 主题 5 分钟体验时长;免费试用彩色容器 / 彩色网格时只写 `previewDisplayMode` 快照,过期或离开试用后按 `coloredContainer -> container`、`coloredGridContainer -> gridContainer` 回落。
- `src/Apptag/ProAccessViews.swift`
- `C1.source/Apptag/ProAccessViews.swift`
  - `ProStatusPill`:高级功能入口的小型 Pro 胶囊;Pro / 已锁定高级功能使用金色皇冠体系,免费状态使用中性胶囊。
  - `ProUpgradePromptView`:功能被锁时的统一解锁提示,购买 / 恢复动作由调用方闭包绑定。
- `src/Apptag/AppGridSupport.swift`
  - 图标气泡、基础 metrics、气泡 placement 支撑。
- `src/Apptag/TagNavigationView.swift`
- `C1.source/Apptag/AppGridSupport.swift`
  - 图标气泡、基础 metrics、气泡 placement 支撑;备注编辑气泡使用原生 `NSTextField` 桥接,placeholder 需显式使用次级但可读的浅色 attributed string,避免系统默认 placeholder 在深色浮层上近似消失。
- `C1.source/Apptag/TagNavigationView.swift`
  - AppKit 标签导航栏,支持标签 hover 滚动、选中、拖放、双击进入标签设置页;标签按钮颜色优先使用 `TagDef.customColor`。
- `src/Apptag/AppDragCoordinator.swift`
- `C1.source/Apptag/AppDragCoordinator.swift`
  - 全局拖拽目标注册、命中判断、容器间拖放、容器外空白移除标签。
  - 拖到容器外/容器之间空白区域时显示 Core Animation 碎纸预览;容器内部空白不触发解除标签预览。
## 数据层
- `src/Apptag/DataLayer.swift`
- `C1.source/Apptag/DataLayer.swift`
  - `AppInfo`:应用模型。
  - `AppDisplayNameResolver`:多语言应用显示名解析。
  - `AppIndexer`:扫描 `/Applications` 等应用来源,处理 bundle / wrapper / localized display name。
  - `AppIndexer`:扫描 `/Applications` 等应用来源,处理 bundle / wrapper / localized display name;主分组生成时通过 `AppContainerID.isReservedGroupName` 跳过被错误写成普通标签的未分类 / Mac 自带 / 不常用等保护容器名,避免本地化显示名重复导致标签导航 fatal。
  - `TagGroup` / `TagColor` / `TagCustomColor`:标签分组、基础色和可选 sRGB 自定义色;`TagDef.customColor` 为可选字段,旧 JSON 缺字段时保持兼容。
  - `TagDatabase`:标签、备注、隐藏状态、分类方案、导入导出、备份和持久化。
  - `TagEditor`:把数据库中的标签/备注/隐藏状态标注回扫描到的 App 列表;`setCustomColor` 是写入自定义标签颜色的唯一数据层入口,必须先过 Pro gate,基础色切换会清除自定义色。
- `src/Apptag/TagEditorView.swift`
- `C1.source/Apptag/TagEditorView.swift`
  - 标签设置页编辑器,负责新建、重命名、删除、基础色选择和自定义颜色入口。
  - 自定义颜色入口显示为横向色条叠加白色线型皇冠 Pro 图标,不显示“自定义颜色”文字;免费态点击只触发 Pro 提示,Pro 态继续通过 macOS 原生 `ColorPicker` / color well 打开颜色选择。
- `src/Apptag/AppLibraryController.swift`
- `C1.source/Apptag/AppLibraryController.swift`
  - App 刷新、SmartStart 应用、系统分类方案应用、重置未分类等业务入口。
  - 持有最近一次完整 `AppLibrarySnapshot`,供新建 overlay 立即复用。
- `src/Apptag/AppDefaults.swift`
- `C1.source/Apptag/AppDefaults.swift`
  - UserDefaults 默认值注册与 schema 默认处理。
  - 新安装默认图标大小为 `56`;已有用户的持久化图标大小不做迁移覆盖。
  - 旧 `useDarkAppGrid=true` 在没有新 theme key 时迁移到 `appGridThemeID=deepBlue`。
@@ -100,134 +102,143 @@
## Quick Search 与快捷键
- `src/Apptag/QuickSearch.swift`
- `C1.source/Apptag/QuickSearch.swift`
  - `LauncherHotkey` / `LauncherHotkeyKind`:主面板和 Quick Search 快捷键定义。
  - `LauncherHotkeyRegistrationStore`:快捷键注册状态持久化。
  - `QuickSearchDocument` / `QuickSearchEngine`:搜索索引与排序。
  - `QuickSearchDocument` / `QuickSearchEngine`:搜索索引与排序;`selectedTagName` 是运行时单选筛选条件,先按真实标签精确收窄文档,再与文本 token 做交集。无文本但已选标签时列出该标签下 App;无标签筛选的空搜索继续保持最近/常用候选。
  - `QuickSearchTagFilterOption` / `QuickSearchTagFilterBar` / `QuickSearchTagFilterChip`:搜索框下方、结果列表上方的单行横向标签筛选条;只在存在真实可用标签时显示,包含本地化 `全部` 和真实标签胶囊,不改结果长条列表形态。
  - `QuickSearchPanelPresentationView` / `QuickSearchOverlayView` / `QuickSearchResultListHostView`:Quick Search 浮层 UI 与结果列表;Quick Search 面板必须是可成为 key 的激活面板,不能使用 `.nonactivatingPanel`,否则 Return 可能落到前一个前台 App。
  - `QuickSearchPanel.sendEvent` 对左键点击做 AppKit 层兜底:先通过 `hitTest` 解析 `QuickSearchResultRowView`,失败时按窗口坐标递归扫描结果行几何命中,并走同一启动路径,避免 SwiftUI / NSHostingView / NSScrollView 层级吞掉候选行点击。
  - `QuickSearchPanel.sendEvent` 对左键点击做 AppKit 层兜底:先解析 `QuickSearchTagFilterClickTargetView` 并触发标签筛选 / 清除;再通过 `hitTest` 和窗口坐标递归几何命中解析 `QuickSearchResultRowView` 并走同一启动路径,避免 SwiftUI / NSHostingView / NSScrollView 层级吞掉标签 chip 或候选行点击。
  - `QuickSearchResultRowView`:结果行内部文字、图标、标签区域统一命中到整行,保证点击任意可见区域都能启动并关闭浮层。
  - `QuickSearchTextField` 同时保留 field editor command delegate 和 `NSControl.target/action` submit fallback,保证 Return / Enter 都能进入 `.submit`。
- `src/Apptag/LauncherHotkeySettings.swift`
- `C1.source/Apptag/LauncherHotkeySettings.swift`
  - `LauncherHotkeySettings`:Pro 自定义全局快捷键的存储、有效值、结构校验、系统保留组合和内部重复校验事实源。
  - 自定义快捷键存储命名空间为 `customHotkeys.v1`;免费用户、无效保存值或内部重复值都回退内置默认快捷键。
  - 修饰键校验允许 Option-only(例如 `Option+Space`),仍拒绝无修饰键、Shift-only,以及 Fn-only 非 Space。
  - `effectiveHotkey(for:)` 不调用公开 `validationError(for:)`,避免重复校验递归。
  - Carbon 的 F1-F12 keyCode 不连续,支持性判断必须使用显式 `functionKeyCodes` 集合,不能写 `kVK_F1...kVK_F12` 范围。
- `src/Apptag/ApptagApp.swift`
- `C1.source/Apptag/ApptagApp.swift`
  - `registerConfiguredHotkeys()` 只注册 `LauncherHotkeySettings.effectiveHotkey(for:)`。
  - `applyCustomHotkey(_:for:)` / `restoreDefaultHotkey(for:)` 是设置页写入自定义快捷键和恢复默认的唯一入口;候选快捷键必须先 Carbon 注册成功,再替换旧 ref 并持久化。
  - 设置页录制自定义快捷键期间,`suspendConfiguredHotkeysForRecording()` 会临时注销主面板和 Quick Search 全局快捷键;录制成功、失败、取消、切 tab、窗口消失或 Pro 权益变更时通过 `resumeConfiguredHotkeysAfterRecording()` 恢复 effective hotkeys。
## 智能分类与 Apple 默认应用资料
- `src/Apptag/SmartCategorization/SmartCategory.swift`
- `C1.source/Apptag/SmartCategorization/SmartCategory.swift`
  - 内置智能分类定义。
  - `SmartCategoryDefaults.orderedIDs` 是 SmartStart 默认初始化标签事实源;当前默认方案为 12 个标签。
  - `SmartCategoryID.smartStartDefaultCategoryID` 负责把旧细分 catalog 分类归并到 12 个默认标签;`Meeting` 归入 `communication`,`finance` 和 `other` 返回 nil,回到未分类;这是新 SmartStart 写入前的归并,不做老用户旧标签自动迁移。
- `src/Apptag/SmartCategorization/SmartCategorizationDraft.swift`
- `C1.source/Apptag/SmartCategorization/SmartCategorizationDraft.swift`
  - 智能分类草稿、默认备注 provenance、未分配应用和 warning 模型。
- `src/Apptag/SmartCategorization/SmartStartService.swift`
- `C1.source/Apptag/SmartCategorization/SmartStartService.swift`
  - SmartStart 初始化、catalog/notes 快照加载、分类结果生成。
- `src/Apptag/AppleDefaultAppCatalog.swift`
- `C1.source/Apptag/AppleDefaultAppCatalog.swift`
  - Apple 自带应用分类和本地化备注 catalog 加载。
- `src/Apptag/SmartStartNoticeOverlay.swift`
- `C1.source/Apptag/SmartStartNoticeOverlay.swift`
  - 首次智能整理提示弹窗。
## 本地化与文档
- `src/Apptag/L10n.swift`
- `C1.source/Apptag/L10n.swift`
  - 语言选择、translation JSON 加载、帮助文档入口。
- `src/Apptag/Localization/*.json`
- `C1.source/Apptag/Localization/*.json`
  - App UI 本地化文案。新增用户可见文案时必须覆盖全部 29 个语言文件,并验证 JSON 合法。
  - `smart.category.*` 是 SmartStart/default system tag 的显示事实源;非英文语言不得直接复制英文初始化标签。
- `src/Apptag/Resources/`
- `C1.source/Apptag/Resources/`
  - SmartStart、Apple default catalog、帮助文档等运行时资源。
- `src/Docs/Requirements/`
- `C1.source/Docs/Requirements/`
  - 需求 todo、工作日志、QA 记录和重要实现结论。
## 构建与发布
- `src/Apptag/Info.plist`
- `C1.source/Apptag/Info.plist`
  - App 版本、build、bundle metadata;注册公开 URL Scheme `taglauncher`,首期路由只支持 `taglauncher://show`。
- `src/Apptag/TagLauncher.entitlements`
- `C1.source/Apptag/TagLauncher.entitlements`
  - App sandbox / entitlement 配置。
- `src/build.sh`
- `C1.source/build.sh`
  - 构建 `.app` 的主入口。
- `src/make_dmg.sh`
- `C1.source/make_dmg.sh`
  - 生成 DMG 的主入口。
- `src/Release/`
  - 发布归档、App Store Connect metadata、审核说明、QA 证据。
- `K3.运营与发布资料/Release/`
  - 发布归档文档、App Store Connect metadata、审核说明、QA 证据。
- `C2.builds/`
  - 当前迁入或生成的 `.dmg` / `.pkg` 构建产物。
## 主要 QA 入口
- `src/Scripts/macos14_availability_typecheck_qa.sh`
- `C1.source/Scripts/macos14_availability_typecheck_qa.sh`
  - macOS 14 API 可用性/typecheck 检查。
- `src/Scripts/macos14_build_metadata_qa.sh`
- `C1.source/Scripts/macos14_build_metadata_qa.sh`
  - build metadata 检查。
- `src/Scripts/apple_default_apps_resource_qa.sh`
- `C1.source/Scripts/apple_default_apps_resource_qa.sh`
  - Apple 默认应用 catalog 资源检查。
- `src/Scripts/apple_default_note_policy_qa.sh`
- `C1.source/Scripts/apple_default_note_policy_qa.sh`
  - Apple 默认备注语言/策略检查。
- `src/Scripts/apple_default_note_migration_qa.sh`
- `C1.source/Scripts/apple_default_note_migration_qa.sh`
  - Apple 默认备注迁移检查。
- `src/Scripts/smartstart_catalog_resource_qa.sh`
- `C1.source/Scripts/smartstart_catalog_resource_qa.sh`
  - SmartStart catalog 资源检查。
- `src/Scripts/smart_category_localization_qa.sh`
- `C1.source/Scripts/smart_category_localization_qa.sh`
  - SmartCategory/default system tag 初始化标签 29 语种本地化检查;禁止非英文语言包直接复制英文标签,保留 `PDF`、`DevOps` 等技术通用词例外。
- `src/Scripts/smartstart_default_categories_qa.sh`
- `C1.source/Scripts/smartstart_default_categories_qa.sh`
  - SmartStart 默认初始化标签检查;验证 12 个默认分类、catalog 分类归并入口、`Meeting` 归入 `communication`、`finance` / `other` 回未分类、首次 starter tags 和关键多语言目标文案。
- `src/Scripts/quick_search_app_name_qa.sh`
- `C1.source/Scripts/quick_search_app_name_qa.sh`
  - Quick Search 应用显示名回归。
- `src/Scripts/quick_search_system_app_qa.sh`
- `C1.source/Scripts/quick_search_system_app_qa.sh`
  - Quick Search 系统应用回归。
- `src/Scripts/quick_search_launch_contract_qa.sh`
- `C1.source/Scripts/quick_search_tag_filter_qa.sh`
  - Quick Search 标签筛选静态门禁;检查运行时单选标签筛选、`全部` 清除、tag chip 原生鼠标命中兜底、空搜索 + 标签列出该标签 App、标签 + 关键词交集、保护容器名从 Quick Search / 主分组排除且导航复用不因重复显示名 fatal、标签条横向胶囊、结果仍走长条候选项和 29 语种本地化 key 完整。
- `C1.source/Scripts/quick_search_launch_contract_qa.sh`
  - Quick Search 启动路径静态门禁;检查 in-app mouse monitor 不吞结果行点击、面板是激活 key panel、panel-level `sendEvent` 点击兜底存在、Return submit fallback 存在、点击 / submit 都接到 `NSWorkspace.openApplication` 启动路径。
- `src/Scripts/pro_custom_hotkeys_qa.sh`
- `C1.source/Scripts/windowserver_event_safety_qa.sh`
  - WindowServer / TextInput 事件安全静态门禁;检查 Quick Search marked-text 输入保护、composition 期间不响应鼠标 / 背景关闭、面板置前去重,以及 TagNavigation 阻塞式事件循环兜底退出。
- `C1.source/Scripts/app_note_bubble_input_qa.sh`
  - App note 泡泡输入框 IME / placeholder 可读性门禁;检查备注泡泡使用原生 `NSTextField` 桥接、placeholder 使用显式次级浅色 attributed string、marked text 期间不覆盖/截断/提交,最终提交仍受备注长度上限约束。
- `C1.source/Scripts/pro_custom_hotkeys_qa.sh`
  - Pro 自定义快捷键静态与 Carbon 运行时门禁;检查 Pro gate、录制期间暂停/恢复全局快捷键、事务式注册保存、重复校验、禁用重权限键盘 API、设置页 Pro 按钮组合和 29 语种文案。
- `src/Scripts/pro_tag_custom_color_qa.sh`
- `C1.source/Scripts/pro_tag_custom_color_qa.sh`
  - Pro 自定义标签颜色门禁;检查 `TagCustomColor` 数据模型、`TagDef.customColor` 兼容字段、Pro gate、原生颜色选择器、免费态 Pro 提示、基础色回退、横向皇冠色条入口和 AppGrid/标签导航显示传播。
- `src/Scripts/pro_notes_quota_qa.sh`
- `C1.source/Scripts/pro_notes_quota_qa.sh`
  - 免费 3 条应用备注 / Pro 无限备注门禁;检查新增第 4 条备注拦截、编辑已有备注不占额度、删除释放额度,以及界面文案不再出现旧 5 条额度。
- `src/Scripts/tag_navigation_hover_scroll_qa.sh`
- `C1.source/Scripts/tag_navigation_hover_scroll_qa.sh`
  - 标签导航 hover 滚动回归。
- `src/Scripts/tag_double_click_preferences_qa.sh`
- `C1.source/Scripts/tag_double_click_preferences_qa.sh`
  - 标签双击进入标签设置页回归。
- `src/Scripts/theme_settings_qa.sh`
- `C1.source/Scripts/theme_settings_qa.sh`
  - 8 个主题、Theme tab、旧深色偏好迁移、编辑模式默认浅色 override、29 语种主题文案回归。
- `src/Scripts/pro_localization_qa.sh`
- `C1.source/Scripts/pro_localization_qa.sh`
  - Pro 文案 29 语种静态门禁;检查 `pro.*`、设置页 Pro 状态/对比表、自定义标签颜色、Quick Search 快捷键页和气泡提示设置键完整、占位符完整、无生成污染和非英文语言无英文兜底复制。
- `src/Scripts/pro_feature_gate_qa.sh`
  - Pro 功能源码门禁;检查 StoreKit 权益、老用户自动 Pro、主题门禁、导入导出硬拦截、3 条备注额度、自定义标签颜色、自定义快捷键、排序预览、Pro UI 提示、设置页线型图标、轻量 Pro 权益行、Pro 页签、免费列“不支持”状态和 About 页不回归 Pro 汇总卡。
- `src/Scripts/pro_theme_preview_countdown_qa.sh`
- `C1.source/Scripts/pro_feature_gate_qa.sh`
  - Pro 功能源码门禁;检查 StoreKit 权益、老用户自动 Pro、主题门禁、导入导出硬拦截、3 条备注额度、自定义标签颜色、自定义快捷键、容器内 App 排序预览、Pro UI 提示、设置页线型图标、轻量 Pro 权益行、固定 Pro 行不回归外层圆角矩形框、Pro 页签、免费列“不支持”状态和 About 页不回归 Pro 汇总卡。
- `C1.source/Scripts/pro_theme_preview_countdown_qa.sh`
  - Pro 主题 / 彩色显示模式预览倒计时门禁;检查状态行倒计时、当前预览卡片 `MM:SS`、到期清理、29 语种 `%time%` 占位符和禁止写死体验时长。
- `src/Scripts/pro_display_mode_preview_qa.sh`
- `C1.source/Scripts/pro_display_mode_preview_qa.sh`
  - Pro 彩色显示模式门禁;检查彩色容器 / 彩色网格锁定、免费态 effective 回落、5 分钟不落盘试用、设置页 Pro badge / 倒计时固定槽位和 AppGrid effective 渲染。
- `src/Scripts/appgrid_startup_loading_qa.sh`
- `C1.source/Scripts/appgrid_startup_loading_qa.sh`
  - AppGrid 快照复用和延迟转圈回归。
- `src/Scripts/url_scheme_activation_qa.sh`
- `C1.source/Scripts/url_scheme_activation_qa.sh`
  - 外部 URL 唤起门禁;检查 `taglauncher://show` 注册、AppDelegate show/focus 语义、冷启动 pending、29 语种设置文案和禁止私有触控板捕获。
- `src/Scripts/usage_tips_qa.sh`
- `C1.source/Scripts/usage_tips_qa.sh`
  - AppGrid 使用技巧 AppKit 横幅、主题可读性、防穿透、关闭按钮、29 语种文案回归。
- `src/Scripts/usage_tips_close_reminder_qa.sh`
- `C1.source/Scripts/usage_tips_close_reminder_qa.sh`
  - 使用技巧关闭提醒、modal 防穿透、设置页预览、29 语种文案回归。
- `src/Scripts/window_logic_qa.sh`
- `C1.source/Scripts/window_logic_qa.sh`
  - 窗口层级、显示隐藏、Dock/菜单栏相关逻辑回归;Dock 项断言按当前 QA 构建路径过滤,避免本机固定正式版 App 时误判重复图标。
- `src/Scripts/settings_language_title_qa.sh`
- `C1.source/Scripts/settings_language_title_qa.sh`
  - 设置窗口标题栏语言刷新静态门禁;检查创建标题、语言切换通知和恢复窗口 `onAppear` 都回写本地化 `NSWindow.title`。
- `src/Scripts/app_ordering_data_qa.sh`
- `C1.source/Scripts/app_ordering_data_qa.sh`
  - App 排序数据持久化回归。
## 受保护行为
- 不得擅自改变源码根目录边界:App 源码只在 `src/` 下维护。
- 不得擅自改变源码根目录边界:App 源码只在 `C1.source/` 下维护。
- 不得把主题、视觉偏好、窗口状态混入 `TagDatabase` 的分类/标签业务数据。
- 主题变化只允许影响 AppGrid 视觉,不得改变标签数据、排序、备注、SmartStart/category scheme、Quick Search、拖拽语义或导入导出。
- Pro 门禁不得写脏免费用户真实数据:主题预览不写 `appGridThemeID`,排序预览不写 `containerAppOrder`,第 6 个新备注不写 `appNotes` / `appNoteMetadata`,导入 / 导出拦截必须早于文件面板和文件读写。
- Pro 门禁不得写脏免费用户真实数据:主题预览不写 `appGridThemeID`,容器内 App 排序预览不写 `containerAppOrder`,第 6 个新备注不写 `appNotes` / `appNoteMetadata`,导入 / 导出拦截必须早于文件面板和文件读写。
- 自定义标签颜色是 Pro 功能:免费用户可继续使用基础色,已有自定义色继续显示,不能新增或修改为新自定义色;改回基础色必须允许且会清除 `customColor`。
- Pro 状态 UI 必须优先使用设置页签下方固定位置的统一 header;不得在各 tab 内重复塞第二条 Pro 引导。About 不承载 Pro 汇总卡或免费 / Pro 差异说明,Data 不承载营销式大卡,避免挤压数据管理布局。
- 免费主题固定为默认、深蓝、黑色;其它主题只能预览或在 Pro 解锁后持久化。
- `originalAppVersion` 早于免费 + Pro 首个版本的历史用户必须自动获得 Pro;`originalPurchaseDate` 只能作为版本不可判断时的兜底。
- `originalAppVersion` 早于免费 + Pro 首个版本的历史用户必须自动获得 Pro;`originalPurchaseDate` 只能作为版本不可判断时的兜底。当前免费 + Pro 首个版本边界由 `ProEntitlementConfig.firstFreeProVersion` 统一维护为 `8.3.2`,用于保护 8.2.9 及更早付费下载用户。
- 默认主题必须保留原浅色毛玻璃 AppGrid。
- 黑色主题背景必须为 100% 纯黑;深蓝和黑色使用深色玻璃;粉色、紫色、绿色、蓝色、炫彩使用浅色玻璃以保证明亮和可读。
- 单个 AppGrid 容器保持统一半透明玻璃面板,不做容器内部渐变。
@@ -235,9 +246,10 @@
- 旧用户 `useDarkAppGrid=true` 必须迁移到 `deepBlue` 主题。
- AppGrid 启动或重开不应因为新 `ContentView` 初始 `allApps.isEmpty` 立刻显示转圈;应先复用最近一次完整快照,并延迟显示 loading。
- Quick Search 显示标题应优先使用解析后的 `AppInfo.displayName`,内部 bundle 名只作为搜索字段。
- Quick Search 标签筛选条只做 V1 单选运行时过滤:显示 `全部` + 当前索引中真实存在的标签;不得显示未分类 / Mac 自带 / 不常用等保护容器;点击已选标签或 `全部` 清除,并由原生鼠标命中兜底保持面板稳定打开;选中标签后输入关键词必须取交集;不得改成方块矩阵、不得持久化筛选状态。
- Quick Search 结果行内部文字 / 图标区域不得吞掉点击;点中行内任意可见区域都应按结果启动路径处理。
- Quick Search 打开后必须可靠接收键盘;面板不得是 non-activating panel,展示时必须激活 App 并成为 key window,Return / Enter 必须通过 command delegate 或 target/action fallback 进入 submit。
- Quick Search 打开期间,本地 mouse monitor 不得吞掉 TagLauncher overlayWindow 内部事件;外部点击可关闭 Quick Search,结果行点击必须通过 `QuickSearchResultRowView.mouseDown` 或 `QuickSearchPanel.sendEvent` 兜底进入同一启动路径;panel 级兜底不得只依赖 `hitTest`,必须保留窗口坐标递归几何命中结果行的路径。
- Quick Search 打开期间,本地 mouse monitor 不得吞掉 TagLauncher overlayWindow 内部事件;外部点击可关闭 Quick Search,标签 chip 和结果行点击必须通过对应 native view mouseDown 或 `QuickSearchPanel.sendEvent` 兜底进入同一筛选 / 启动路径;panel 级兜底不得只依赖 `hitTest`,必须保留窗口坐标递归几何命中路径。
- Quick Search-only 点击 TagLauncher 自身结果必须关闭浮层,不得重新打开 AppGrid。
- Apple 默认应用备注必须按当前语言显示,不允许 A 语言出现 B 语言备注。
- SmartStart/default system tag 初始化标签必须按当前语言显示;升级用户启动后应重刷带 `systemCategoryID` 的系统标签,不能长期保留旧英文初始化标签。