From bbd86bd724465269895ffd9468927a4a86f4a98c Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Thu, 11 Jun 2026 20:46:21 +0800
Subject: [PATCH] Organize 7.9 app ordering docs

---
 docs/7.90/02-专题讨论纪要.md          |   62 +++++++++++++++
 src/TODO.md                     |   40 +---------
 docs/7.90/01-容器内App手动排序-TODO.md |   68 +++++++++++++++++
 docs/7.90/README.md             |   29 +++++++
 4 files changed, 163 insertions(+), 36 deletions(-)

diff --git "a/docs/7.90/01-\345\256\271\345\231\250\345\206\205App\346\211\213\345\212\250\346\216\222\345\272\217-TODO.md" "b/docs/7.90/01-\345\256\271\345\231\250\345\206\205App\346\211\213\345\212\250\346\216\222\345\272\217-TODO.md"
new file mode 100644
index 0000000..bd7751d
--- /dev/null
+++ "b/docs/7.90/01-\345\256\271\345\231\250\345\206\205App\346\211\213\345\212\250\346\216\222\345\272\217-TODO.md"
@@ -0,0 +1,68 @@
+# 容器内 App 手动拖拽排序 TODO
+
+## 目标
+
+用户可以在同一个容器/分组内拖动 App,改变该容器内默认显示顺序;重启、刷新、语言切换、导入导出、恢复布局后顺序仍保持。
+
+## 版本
+
+- 起始版本:`7.9.0`
+- 需求级别:较大需求
+- 当前状态:方案确认,待开发
+
+## 核心决策
+
+- 这不是纯 UI 数组重排;App 顺序必须作为“分类与布局方案”的一部分持久化到 `TagDatabase.Store`。
+- 第一版只支持同一容器内排序,不改变 App 的标签归属。
+- 跨容器拖动继续沿用现有移动/复制标签逻辑。
+- 拖到空白区域继续沿用现有移除来源标签/归为未分类确认逻辑。
+- 不改 Quick Search 排名,不改 `appTags[path]` 语义,不存像素坐标、row/column 或 `IndexPath`。
+
+## 数据层 TODO
+
+- 在 `TagDatabase.Store` 新增 `containerAppOrder: [String: [String]]`,旧 JSON 用 `decodeIfPresent` 默认空字典。
+- 定义稳定容器 ID,不能用本地化显示名;建议普通标签 `tag:<tagName>`,系统分类 `system:<SmartCategoryID>`,特殊容器 `__container.uncategorized` / `__container.appleBuiltIn`。
+- `TagGroup` 或分组构造链路携带稳定 container key,显示名继续只用于 UI。
+- 在 `makeDisplayGroups` / 分组生成后按 `containerAppOrder` 排组内 apps;未命中的新 App 按现有默认名称排序追加。
+- 新增 `TagEditor.reorderApps(inContainer:orderedPaths:)`,走 `saveUserCategorySchemeMutation(reason: "reorder-apps")`。
+- `CategorySchemeFingerprint` 纳入 `containerAppOrder`,确保自动快照、恢复上一方案和导出/导入不会漏掉顺序。
+- tag rename/delete/relocalize、卸载 App reconcile、未分类重置、SmartStart replace 必须同步迁移或清理顺序字段。
+
+## UI TODO
+
+- 不使用 SwiftUI `onDrag/onDrop`;当前 App Grid 是 AppKit `NSViewRepresentable` + 自绘拖拽,应在 `AppGridCollectionView` / `AppGridGroupCardView` / `AppGridIconNSView` 链路扩展。
+- 为同容器排序增加独立 intent 和 insertion index hit-test,避免误触发跨标签移动、复制、拖空白移除或 Apple 内置保护逻辑。
+- 第一版可只显示插入位置指示线/占位,不做复杂跨容器预览。
+- 排序开始时继续抑制 hover bubble;结束、取消、滚动、Esc、切换窗口时必须清理拖拽状态。
+- 编辑模式的批量添加/移除标签界面第一版不开放 App 排序,只读取排序结果。
+
+## 推荐开发切分
+
+1. 数据层 PR:
+   - schema、容器 ID、排序 helper、fingerprint、导入导出/恢复/重置/SmartStart 规则。
+   - 先不接 UI。
+
+2. UI hit-test PR:
+   - 同容器插入位置计算和本地预览。
+   - 不落盘,不改变跨容器拖拽。
+
+3. 集成 PR:
+   - `ContentView` 接入 reorder callback。
+   - drop/end 时保存该容器完整顺序并刷新。
+
+4. 回归 PR:
+   - 数据脚本 QA、macOS 14 typecheck/build、窗口/拖拽 smoke、真实鼠标手工验收。
+
+## QA 阻断项
+
+- 旧 `tags.json` 无顺序字段可加载,默认顺序与现版本一致。
+- 新字段导出/导入 roundtrip 保留顺序;恢复上一方案恢复顺序。
+- 排序后刷新、重启、语言切换、SmartStart 备份/恢复均不丢顺序。
+- 同容器排序不破坏跨容器移动/Option 复制、拖空白移除、拖到 Apple 内置保护。
+- 多标签 App 在 A 容器排序不影响 B 容器顺序。
+- macOS 14、5 种 displayMode、左/右/顶部标签位置、hide names 开关、icon size 40/64/80 至少 smoke。
+
+## 风险等级
+
+- 最小方案:中等。
+- 一次性做跨容器插入、跨机器稳定匹配、复杂拖拽 payload 和所有模式完整预览:高。
diff --git "a/docs/7.90/02-\344\270\223\351\242\230\350\256\250\350\256\272\347\272\252\350\246\201.md" "b/docs/7.90/02-\344\270\223\351\242\230\350\256\250\350\256\272\347\272\252\350\246\201.md"
new file mode 100644
index 0000000..c83baa1
--- /dev/null
+++ "b/docs/7.90/02-\344\270\223\351\242\230\350\256\250\350\256\272\347\272\252\350\246\201.md"
@@ -0,0 +1,62 @@
+# 容器内 App 手动排序专题讨论纪要
+
+## 用户目标
+
+- 用户希望在容器中,每个 App 的位置可以拖动,改变默认显示顺序。
+- 本轮要求拉 2 个架构师、1 个代码审核员、1 个 QA 做专题讨论,评估可行性、开发风险和最优方案。
+
+## 参与视角
+
+- 架构师 A:数据模型、分类方案、导入导出、SmartStart 影响。
+- 架构师 B:App Grid / 容器视图 / 拖拽交互。
+- 代码审核员:风险、必须避免的实现方式、代码切分。
+- QA:验收矩阵、自动化与人工验证边界。
+
+## 关键结论
+
+- 功能可做,但不能只做 UI 数组重排;必须把容器内 App 顺序持久化到 `TagDatabase.Store`。
+- 当前 App 默认顺序来自扫描后名称排序,`AppIndexer.group()` 只负责分组,组内顺序没有用户字段。
+- 推荐新增 `containerAppOrder: [String: [String]]`,按稳定容器 ID 保存每个容器内的 app path 顺序。
+- 容器 ID 不能使用本地化显示名;建议使用 `tag:<tagName>`、`system:<SmartCategoryID>`、`__container.uncategorized`、`__container.appleBuiltIn` 等稳定 key。
+- 新字段必须纳入分类方案快照、导出、导入、恢复、SmartStart 回滚;否则“分类与布局”导出会丢布局。
+- 第一版只支持同一容器内拖动排序;跨容器移动/复制标签、拖到空白移除标签、Apple 内置保护等旧行为保持不变。
+- 不建议使用 SwiftUI `onDrag/onDrop`。当前 App Grid 是 AppKit `NSViewRepresentable` + 自定义拖拽,拖拽排序应在 `AppGridCollectionView` / `AppGridGroupCardView` / `AppGridIconNSView` 链路扩展。
+
+## 推荐开发切分
+
+1. 数据层:
+   - `Store` 增加 `containerAppOrder`,兼容旧 JSON。
+   - 增加容器 ID helper 和排序 helper。
+   - `CategorySchemeFingerprint` 纳入顺序字段。
+   - 导入、导出、恢复、未分类重置、SmartStart replace、tag rename/delete/relocalize 清理或迁移顺序。
+
+2. UI hit-test:
+   - `AppGridCollectionView` 增加同容器插入位置计算。
+   - 排序拖拽与现有跨 tag 移动/复制拖拽隔离。
+   - 先做本地预览,不落盘,不改跨容器行为。
+
+3. 集成:
+   - `ContentView` 增加 reorder callback。
+   - drop/end 时保存该容器完整顺序。
+   - 刷新 `displayGroups` 后顺序保持。
+
+4. QA:
+   - 旧 JSON 兼容、新 JSON roundtrip、导入导出、恢复、重置、SmartStart 数据断言。
+   - macOS 14 typecheck/build metadata/window logic/Quick Search/SmartStart 现有回归。
+   - 真实鼠标拖拽、滚动拖拽、显示模式、标签位置、编辑模式必须人工 smoke。
+
+## 风险评估
+
+- 最小方案风险:中等。
+- 若一次性支持跨容器插入、跨机器稳定匹配、复杂拖拽 payload、所有显示模式完整预览,风险升为高。
+- 最大风险点:
+  - 刷新/重启后顺序丢失。
+  - 导入导出/恢复/SmartStart 漏掉顺序。
+  - 同容器排序误触发跨容器移动、复制、移除标签确认。
+  - 用本地化显示名做 key 导致语言切换后顺序错位。
+  - 编辑模式、tag 拖拽排序、hover bubble、滚动抑制互相冲突。
+
+## 建议决策
+
+- 先做低风险 spike:只做同容器排序,path-based 顺序持久化,所有 display mode 读取排序,但第一版优先在容器/网格容器拖拽入口验证。
+- 暂不改 Quick Search 排名,不改 `appTags` 语义,不存像素坐标/IndexPath,不把顺序放 UserDefaults。
diff --git a/docs/7.90/README.md b/docs/7.90/README.md
new file mode 100644
index 0000000..5b8d181
--- /dev/null
+++ b/docs/7.90/README.md
@@ -0,0 +1,29 @@
+# TagLauncher 7.9.0 需求包
+
+## 版本边界
+
+- 本目录用于归档 7.9.x 大需求的方案、TODO、过程纪要和后续验收资料。
+- “容器内 App 手动拖拽排序”属于较大需求,版本记录从 `7.9.0` 开始,不继续放在 `7.8.x` 小版本序列里。
+- 当前只完成方案确认和任务拆解,尚未进入代码实现。
+
+## 需求主题
+
+用户希望在容器中,每个 App 的位置可以拖动,从而改变该容器内默认显示顺序。
+
+核心决策:
+
+- 这不是纯 UI 数组重排;App 顺序必须成为“分类与布局方案”的一部分。
+- 第一版只支持同一容器内排序,不改变 App 标签归属。
+- 跨容器拖动、Option 复制、拖到空白移除标签、Apple 内置保护等现有行为保持不变。
+- 不改 Quick Search 排名,不改 `appTags[path]` 语义。
+
+## 文件索引
+
+- [01-容器内App手动排序-TODO.md](./01-容器内App手动排序-TODO.md):可执行开发 TODO、切分和 QA 阻断项。
+- [02-专题讨论纪要.md](./02-专题讨论纪要.md):2 个架构师、1 个代码审核员、1 个 QA 的专题讨论结论。
+
+## 后续记录规则
+
+- 真正开始实现时,应从 `7.9.0` 更新版本、build、changelog 和发布资料。
+- 每个开发阶段单独提交、单独构建、单独 QA。
+- 完成阶段性实现后,将验证结果继续补充到本目录,而不是散落在会话记录里。
diff --git a/src/TODO.md b/src/TODO.md
index 8f86fc7..16d53c8 100644
--- a/src/TODO.md
+++ b/src/TODO.md
@@ -13,42 +13,10 @@
 
 ## Todo
 
-- [新需求] 容器内 App 手动拖拽排序。
-  - 目标: 用户可以在同一个容器/分组内拖动 App,改变该容器内默认显示顺序;重启、刷新、语言切换、导入导出、恢复布局后顺序仍保持。
-  - 核心决策: 这不是纯 UI 数组重排;App 顺序必须作为“分类与布局方案”的一部分持久化到 `TagDatabase.Store`。
-  - 最小版本范围:
-    - 只支持同一容器内排序,不改变 App 的标签归属。
-    - 跨容器拖动继续沿用现有移动/复制标签逻辑。
-    - 拖到空白区域继续沿用现有移除来源标签/归为未分类确认逻辑。
-    - 不改 Quick Search 排名,不改 `appTags[path]` 语义,不存像素坐标、row/column 或 `IndexPath`。
-  - 数据层 TODO:
-    - 在 `TagDatabase.Store` 新增 `containerAppOrder: [String: [String]]`,旧 JSON 用 `decodeIfPresent` 默认空字典。
-    - 定义稳定容器 ID,不能用本地化显示名;建议普通标签 `tag:<tagName>`,系统分类 `system:<SmartCategoryID>`,特殊容器 `__container.uncategorized` / `__container.appleBuiltIn`。
-    - `TagGroup` 或分组构造链路携带稳定 container key,显示名继续只用于 UI。
-    - 在 `makeDisplayGroups` / 分组生成后按 `containerAppOrder` 排组内 apps;未命中的新 App 按现有默认名称排序追加。
-    - 新增 `TagEditor.reorderApps(inContainer:orderedPaths:)`,走 `saveUserCategorySchemeMutation(reason: "reorder-apps")`。
-    - `CategorySchemeFingerprint` 纳入 `containerAppOrder`,确保自动快照、恢复上一方案和导出/导入不会漏掉顺序。
-    - tag rename/delete/relocalize、卸载 App reconcile、未分类重置、SmartStart replace 必须同步迁移或清理顺序字段。
-  - UI TODO:
-    - 不使用 SwiftUI `onDrag/onDrop`;当前 App Grid 是 AppKit `NSViewRepresentable` + 自绘拖拽,应在 `AppGridCollectionView` / `AppGridGroupCardView` / `AppGridIconNSView` 链路扩展。
-    - 为同容器排序增加独立 intent 和 insertion index hit-test,避免误触发跨标签移动、复制、拖空白移除或 Apple 内置保护逻辑。
-    - 第一版可只显示插入位置指示线/占位,不做复杂跨容器预览。
-    - 排序开始时继续抑制 hover bubble;结束、取消、滚动、Esc、切换窗口时必须清理拖拽状态。
-    - 编辑模式的批量添加/移除标签界面第一版不开放 App 排序,只读取排序结果。
-  - 推荐开发切分:
-    1. 数据层 PR: schema、容器 ID、排序 helper、fingerprint、导入导出/恢复/重置/SmartStart 规则;先不接 UI。
-    2. UI hit-test PR: 同容器插入位置计算和本地预览,不落盘,不改变跨容器拖拽。
-    3. 集成 PR: `ContentView` 接入 reorder callback,drop/end 时保存该容器完整顺序并刷新。
-    4. 回归 PR: 数据脚本 QA、macOS 14 typecheck/build、窗口/拖拽 smoke、真实鼠标手工验收。
-  - QA 阻断项:
-    - 旧 `tags.json` 无顺序字段可加载,默认顺序与现版本一致。
-    - 新字段导出/导入 roundtrip 保留顺序;恢复上一方案恢复顺序。
-    - 排序后刷新、重启、语言切换、SmartStart 备份/恢复均不丢顺序。
-    - 同容器排序不破坏跨容器移动/Option 复制、拖空白移除、拖到 Apple 内置保护。
-    - 多标签 App 在 A 容器排序不影响 B 容器顺序。
-    - macOS 14、5 种 displayMode、左/右/顶部标签位置、hide names 开关、icon size 40/64/80 至少 smoke。
-  - 风险等级: 最小方案中等;若一次性做跨容器插入、跨机器稳定匹配、复杂拖拽 payload 和所有模式完整预览,风险升为高。
-  - 参考记录: `.codex-sessionhistory/2026-06-11-App容器排序方案.md`。
+- [7.9.0 大需求] 容器内 App 手动拖拽排序。
+  - 状态: 方案已确认,详细 TODO 和过程文档已归档到 `../Docs/7.90/`。
+  - 版本: 后续实现从 `7.9.0` 开始记录,不混入 `7.8.x` 小版本。
+  - 入口: `../Docs/7.90/README.md`、`../Docs/7.90/01-容器内App手动排序-TODO.md`、`../Docs/7.90/02-专题讨论纪要.md`。
 
 - [发布后独立任务] 设置页 tab 容器 AppKit/自控化评估与实现。
   - 决策: 当前发布前 No-Go;保留 SwiftUI `TabView`,不改 QA 脚本。

--
Gitblit v1.9.3