docs:勾选 Plan §5 / §8 Phase 1.10-1.13 进度 + CLAUDE.md 新增「进度同步规范」

把 Plan 任务清单和进度追踪 checklist 同步到当前实际进度(1.10-1.13
均已完成 + 实测验证),并在 CLAUDE.md 写入"每完成 Phase 子项必须立即
更新 Plan 进度"的硬约束。

- Plan §5 Phase 1.10-1.13 任务清单 [ ] → [x]
- Plan §8 进度追踪同步:标注算法名 / 端到端实测结果(260→261 验证)
- CLAUDE.md 新增「进度同步规范」节,规定:
  - Plan §5 + §8 每完成子项立即勾选,与 commit 同 commit 内完成
  - 任务描述与实现有差异时同步修订(不允许 Plan 与代码长期不一致)
  - commit message 末尾备注"Plan 进度已勾选"
  - 理由:Plan 是项目记忆的唯一权威进度视图,新人 clone 后看 Plan
    §8 即可知整体进度;与 commit log 双写互为校验

Plan 进度已勾选
This commit is contained in:
joywayer
2026-06-22 02:30:31 +08:00
parent 0887088bb8
commit 87304552c3
2 changed files with 26 additions and 8 deletions
+8 -8
View File
@@ -262,23 +262,23 @@ Contract Design Plan(本文档)
##### 1.D 远程配置 + 版本对比 + zip 升级(**Phase 1 关键缺口,ADR-008**
- [ ] **1.10** 实现 `ylgamehall/Source/Network/RemoteConfigClient.swift`actor
- [x] **1.10** 实现 `ylgamehall/Source/Network/RemoteConfigClient.swift`actor
- URL 构造:`http://` + `BundleConfig.shared.gameConfig.replacingOccurrences("-", "/")` + `.txt`**注意**:不带 `SERVERNew` 前缀,原 `daoqi/NewRootVC.m:250` 就是这样构造)
- 拉远端 `.txt` 内容(实际是 JSON)→ `URLSession.async data(from:)`10 s 超时
- 指数退避重试(msext 用 4s 等间隔暴力 timer,新外壳用 1s / 2s / 4s 三次)
- 反 JSON → 强类型 `RemoteConfig` Codable 模型(嵌套:`agentlist[].channellist[].marketlist[]` + `agentlist[].gamelist[].channellist[].marketlist[]`
- 单测:mock URLSession + fixture JSON 验证嵌套解析正确
- [ ] **1.11** 实现 `ylgamehall/Source/Network/VersionResolver.swift`(纯函数 + 单测)
- [x] **1.11** 实现 `ylgamehall/Source/Network/VersionResolver.swift`(纯函数 + 单测)
- 输入:`RemoteConfig + (agentId, channelId, marketId, gameId)` 四组 ID
- 输出:`ResolvedVersion { appVersion, appDownload, gameVersion, gameZip }`
- 算法:4 级覆盖合并 —— 顶层 → 当前 agent → 当前 channel → 当前 market(最深胜出);agent 子树和 game 子树分别合并,game 子树最终覆盖 agent 子树
- 参考 `daoqi/NewRootVC.m:1372-1492` 的散落 if/else,新外壳实现成纯 reduce
- 单测:覆盖所有边界(顶层有/无、深层缺失、agent vs game 优先级 4 组场景至少 12 用例)
- [ ] **1.12** 实现 `ylgamehall/Source/Resource/LocalVersionReader.swift`nonisolated namespace
- [x] **1.12** 实现 `ylgamehall/Source/Resource/LocalVersionReader.swift`nonisolated namespace
- `localAppVersion: Int`:从 `BundleConfig.shared.appVersion` 读,转 Int
- `localGameVersion: Int`:读 `Library/Caches/{gamedir}/{gamestart}/version.xml``XMLParser` 解析 `/game/version@value` 转 Int;缺失返回 0
- 单测:fixture xml 验证解析;缺失 / 损坏 xml 返回 0
- [ ] **1.13** 实现 `ylgamehall/Source/Resource/LobbyZipUpgrader.swift`actor
- [x] **1.13** 实现 `ylgamehall/Source/Resource/LobbyZipUpgrader.swift`actor
- `upgradeIfNeeded(remote: ResolvedVersion) async throws -> UpgradeOutcome`
- 比较 `remote.gameVersion > LocalVersionReader.localGameVersion` → 触发下载,否则直接返回 `.noop`
- 下载链路:`URLSession.download(from:)` → 临时文件 `tmp/lobbyzip-{uuid}.zip` → ZIPFoundation 解压到 `tmp/lobbyzip-{uuid}/`**原子 rename**`lobbyRoot`(解压前清空旧 lobbyRoot;不学 msext "目录名 +1" hack
@@ -781,10 +781,10 @@ H5 调 `OpenurlTitleData` 打开弹层 WebView,弹层内 H5 用 `window.settin
- [x] 1.7 BridgeBus
- [x] 1.8 WVJB JS 协议
- [x] 1.9 BridgedWebView
- [ ] 1.10 RemoteConfigClientactorURLSession async + 重试)
- [ ] 1.11 VersionResolver(纯函数 4 级覆盖 + 单测
- [ ] 1.12 LocalVersionReaderversion.xml 解析)
- [ ] 1.13 LobbyZipUpgraderactor,原子 rename 升级)
- [x] 1.10 RemoteConfigClientactorURLSession async + 重试 + cache-busting + 短文本 + FlexibleString
- [x] 1.11 VersionResolverchulishengji 双子树合并算法,纯函数)
- [x] 1.12 LocalVersionReaderversion.xml 解析 + ATS 全局放行
- [x] 1.13 LobbyZipUpgraderactor,原子 rename 升级;端到端实测 260→261
- [ ] 1.14 WebContainerViewController16:9 letterbox + 串接整链路)
- [ ] 1.15 VibratorHandler
- [ ] 1.16 SceneDelegate → WebContainerViewController