Skip to content

第二批 code review 修复:8 个遗留 bug + 6 项技术增强 - #174

Merged
gooooloo merged 18 commits into
mainfrom
code-review-fixes-2
Jun 12, 2026
Merged

第二批 code review 修复:8 个遗留 bug + 6 项技术增强#174
gooooloo merged 18 commits into
mainfrom
code-review-fixes-2

Conversation

@gooooloo

Copy link
Copy Markdown
Owner

概述

#170 之后的第二批修复,处理第一批暂缓的全部 bug 类 issue 与大部分技术增强。计划与执行结果见 `docs/code-review-fix-plan-2.md`。

每个 issue 一个独立 commit,每个 commit 均通过完整 macOS 测试套件;涉及共享/iOS 代码的节点经 iOS Simulator 构建验证。

Bug 修复(8 个,全部完成)

Issue 修复
#127 复习评最后一项时视图下标越界崩溃 → currentReviewItem 安全取值
#155 setFilters 无法显式清除 specificGameId/BookId → IdUpdate 哨兵枚举(.keep/.clear/.set)
#157 录入棋局「记录对弈时间」开关无效 → 关闭时写 nil
#156 棋盘残留选中高亮可提交非法局面 → 监听 fen 变化清除选中
#158 静默云库查分请求风暴 → 在飞去重 + 导航取消 + 指数退避(含 rate limit 检测)
#159 引擎 UCI 读取健壮性 → 整行匹配 / EOF 即时报错 / 退出 2 秒超时强杀
#160 保存抑制窗口吞掉远程变更 → 变更计数代替 Bool + 修改时间 checkpoint 补发
#128 ViewModel 缺 MainActor 隔离 → @mainactor 标注,session 读写收敛主线程

技术增强

Issue 状态 内容
#166 ✅ 完成 SessionData 全字段容错解码;DatabaseData schemaVersion 迁移判断
#165 ✅ 完成 走法合法性:送将/自将(对脸)过滤 + 7 个语义钉住测试
#161 ✅ 完成 引擎分数保存前按 fenId 合并远端文件;iCloud 占位文件触发下载
#162 ✅ 完成 GamePathEnumerator 计数式组合枚举,去除指数级全路径物化;删除重复实现
#164 ✅ 完成 ViewModel.session 收紧 private;3 处 View 层违规改走转发接口
#163 ◐ 部分 紧凑编码 + 版本号字节级扫描;后台化需不可变快照设计(issue 留言)
#167 ◐ 部分 伪测试修复 + 适情雅趣导入测试开关 + 组合视图补测 10 个(issue 留言)
#168 ◐ 部分 Utils.swift 死代码删除;视图重复消除需视觉验证(issue 留言)

测试

  • 全量 macOS 单元测试通过(含新增 30+ 测试)
  • iOS Simulator 构建通过
  • 《适情雅趣》导入测试开关使全套件不再重复支付 550 局导入

备注

🤖 Generated with Claude Code

gooooloo and others added 18 commits June 12, 2026 00:25
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
两处 reviewInProgressView 改为经 ViewModel.currentReviewItem 安全取值,索引越界时不渲染当前项描述。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Optional 参数无法区分「保留」与「清除」;改为 .keep/.clear/.set(id) 三态枚举。deleteGame/deleteBook 后真正清除指向已删对象的残留 id,避免 toggle 回失效视图。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
saveGame() 读取 hasGameDate,关闭时 gameDate 写入 nil(模型字段本为可空,下游显示均已处理 nil)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
XiangqiBoard 监听 fen 变化(键盘导航、加载棋局、切换筛选等),清空 selectedSquare/highlightedSquares,避免点击旧蓝点提交与当前局面无关的非法局面。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
任意时刻至多一个在飞静默请求:同 fenId 去重,导航离开取消旧请求;限流(rate limit 响应改为抛 quotaExceeded)或网络故障后 5s 起指数退避至 60s 上限。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
waitForResponse 只在完整行中匹配关键字,避免半行送达解析出截断 bestmove;poll 可读但读到 0 字节(POLLHUP/EOF)立即抛 engineTerminated,不再热循环空转至 120 秒;stop() 等待退出最多 2 秒后强制 terminate。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
变更通知由可被覆盖的 Bool 改为单调递增计数,消除置位/复位竞态;endSavingDatabase 在窗口结束时用写入后的文件修改时间比对,发现窗口期间文件被远端改写则补发通知;isSavingDatabase 跨线程读写加锁。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
所有 Task { await self.xxx() } 形式的 action handler 现继承 MainActor 隔离,消除后台线程读取 Session/Database 数据与主线程写入的竞态。RemoteControlServer 的 main.sync 调用点用 MainActor.assumeIsolated 声明隔离成立;iOS 平台服务的 alert 经 Task @mainactor 归位主线程;ViewModelTests 整体标注 @mainactor。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
SessionData 所有字段改 decodeIfPresent+默认值,schema 演进时单字段缺失不再导致整体会话重置;DatabaseData 增加 schema_version 字段(存量文件视为 1),文件来自更新版本应用时显式报错而非静默误读。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
getLegalDestinationSquares 拆分为伪合法(几何)+ 模拟落子检测:走后己方被将军(含将帅对脸、王走入攻击线、钉子离线)的着法被剔除;新增 isKingInCheck。受影响的几何测试棋盘改为非对脸布局,并新增 7 个语义钉住测试(钉子、垫将、对脸检测等)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
saveEngineScore 写入前 coordinated read 远端同名文件并合并(远端补充本地缺失项,冲突本地优先,版本取较大者);listEngineKeys 不再跳过隐藏文件,对 iCloud 占位文件触发 startDownloadingUbiquitousItem。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
存档/备份去掉 .prettyPrinted(体积约减半);loadDataVersion 改为原始字节扫描 data_version,不再为读版本号解析整个 JSON(保留完整解析回退)。#163 中「编码与写入后台化」涉及 DatabaseData 可变引用与后台编码的竞态,需要不可变快照设计,留待后续单独处理。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
新增 GamePathEnumerator:记忆化计数 O(节点+边),以子节点 fenId 升序为稳定字典序,支持按序号取路径 / 路径反查序号 / 总数,随机一局 = 均匀随机序号。替换 Session.generateAllGamePaths 的指数级全路径物化;prev/next 路径导航与路径序号显示语义保持。删除 GameOperations 中无生产调用的重复实现 makeRandomGameDFS 系列。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
新增转发接口:练习走错统计(practiceMistakesInScope/resetPracticeMistakes/fenString)、棋局浏览器 UI 状态(读写并标记会话脏,修复直写 sessionData 绕过 dirty 标记)、课程视频关联(CourseVideoStorage 不再被 View 直调)。PracticeMistakeStatsView/GameBrowserView/CommentView 改走转发接口;测试经 sessionManager.currentSession 访问。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
修复 3 个无法失败的伪测试(currentVariationIndex >= 0、jumpToNextOpeningGap 断言包在 if 里、currentGameStep >= 0);Session init 的《适情雅趣》550 局静默导入在测试进程默认跳过(需要的测试用 force: true 显式导入),消除全套件 100+ 次重复支付;补 specificGame/specificBook/withStepLimit/withLock/combined 视图测试 10 个。

剩余项(共享 TestDatabaseBuilder 统一 10 份手工构造、iCloud 同步链路测试、UITests target 修复)保留在 issue。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
删除 stringify/sortKeys/hashString/makeDiff/isEqual/removeNullOrUndefinedValues(全仓库零调用),仅保留在用的 normalizeFen。视图层重复消除与 GameBrowserView 拆分涉及大面积 UI 改动且无测试覆盖,留待单独处理。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@gooooloo
gooooloo merged commit b34b899 into main Jun 12, 2026
@gooooloo
gooooloo deleted the code-review-fixes-2 branch June 28, 2026 06:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant