86 lines
8.5 KiB
Markdown
86 lines
8.5 KiB
Markdown
# 阶段 3A 独立代码审查
|
||
|
||
日期:2026-09-22。审查身份:主实现会话之外的独立审查 agent。
|
||
|
||
## 1. 最终裁决
|
||
|
||
**限定阶段 3A 通过。** 发现的 1 项 P2 路径校验问题已经由主会话修复并经独立回归确认;当前三文件没有剩余已证实阻塞问题。可按已批准方案继续阶段 3B,不能据此宣称整个阶段 3 或生产游戏 KV 切换完成。
|
||
|
||
本次只审查同步状态、快照格式和本地文件持久化,不修改生产代码,不调用正式服,不操作 Unity。独立证据写入 `KVSyncReviewTests/`;主会话测试和编译证据只读核对。
|
||
|
||
## 2. 对照依据及代码范围
|
||
|
||
方案:《阶段3缓存同步方案与评审-2026-09-22.md》,重点第 4–7 节与 G3A;此前方案独立审查的问题已闭环。用户本轮确认继续后,两项保守策略已经批准:未知写不得仅凭 Get 自动解锁;损坏主档不得自动恢复旧备份并继续写。
|
||
|
||
本次生产文件均在 `Client/Assets/Scripts/Services/PlayerData/`:
|
||
|
||
| 文件 | 实际审查范围 | 最终 SHA256 |
|
||
|---|---|---|
|
||
| PlayerKVSyncModels.cs | 身份规范化、不可变对外模型、快照编解码、序号及批次关联 | `49143F3A6DAD9A570C522288B471D5C4CE5812F73E0EB7B8E6081453C97990D4` |
|
||
| PlayerKVCacheStore.cs | 独占锁、加载失败分类、临时文件/flush/原子替换、失败与释放 | `A08DAB00F51A28CB5AA9A26D66CB3EB9349216535E92F4DC4E77EE8DDEBA28B1` |
|
||
| PlayerKVSyncState.cs | 状态转换、基线/待写/本地覆盖、多版本确认、未知恢复、同步 gate/Dispose | `B0BF9EBAA24C8ACB4761B7C09331B81A414E62CDBBF143B106B7F466E334A198` |
|
||
|
||
未将 owner、HTTP 串行调度、异步票据、Close 准入门判定为“缺失实现”:这些明确属于 3B。未扩大到 UserService、PlayFabMgr 或游戏存档接线。
|
||
|
||
## 3. 发现项及闭环
|
||
|
||
### R1 — [P2,已修复] Windows 半绝对路径通过缓存根目录校验
|
||
|
||
- 位置:`PlayerKVSyncModels.cs:101`,`KVIdentity` 的根路径检查。
|
||
- 初审实现使用 `Path.IsPathRooted`。Windows 上 `C:relative` 与 `\relative` 均可返回 true,但并非完整绝对路径;随后 `GetFullPath` 根据当前目录或当前盘符解析。同一参数可能指向不同命名空间,不符合 G3A1 的非法路径拒绝约定。
|
||
- 最小复现:向身份构造/Open 传上述根路径。正常完整绝对路径是对照。问题仅在调用方提供这种非法根目录时触发,没有证据表明现有正常 persistentDataPath 已因此丢数据。
|
||
- 主会话修复:改为 `Path.IsPathFullyQualified`,不改变存储格式或同步算法。独立宿主断言两类路径均拒绝;主测试增加对应两项;Unity 编译证据确认该 API 在当前项目可用。
|
||
- 证据边界:修复发生在独立宿主首次执行之前,因此未伪造“旧源码执行失败”记录。旧实现由初审源码及明确的 Windows 路径语义确认;本报告保存的是修复后实际执行结果。
|
||
|
||
另有初审文档状态提醒:方案末尾一度残留“待用户确认/尚未实现”的旧总结,已反馈主会话同步。此项不属于生产代码缺陷。
|
||
|
||
## 4. 关键正确性核对
|
||
|
||
| 风险 | 核对结果 |
|
||
|---|---|
|
||
| 丢失已接纳编辑 | 每次编辑先克隆快照,保存成功才发布新内存和 Success。失败进入 StorageError,后续编辑/同步启动被拒绝;无失败后静默清队列路径。 |
|
||
| 本地提交不确定 | `Save` 在替换前设置不确定标记;替换后故障返回失败并保留原内存,同时报告目标 revision/attemptSequence 和不确定性。重开按实际主文件恢复,不强行认定本次编辑未保存。 |
|
||
| 损坏加载或错误身份 | 必填类型、未来版本、身份、重复 JSON 属性、完整根、序号界限、待写唯一序号及批次关联均有检查。损坏返回 RecoveryRequired 并释放独占句柄;不把损坏读成空字典。 |
|
||
| 备份退回旧数据 | 有效主文件优先;损坏/缺失主文件且有遗留材料时阻止打开,不自动接受备份。有效主文件不因损坏备份而冻结。 |
|
||
| active 与 v2 混淆 | 批次是不可变快照。v1 发出后可保存 v2;确认仅移除同 sequence,否则保留 v2 的目标并推进 base 至 v1。合法同 key 同 sequence 的引用可加载。 |
|
||
| unknown 在重开时丢失 | 重开遗留 active 在内存转换为 unknown;原磁盘 active 本身仍是再次重开的冻结证据。下一次保存才写成 unknown 不形成放行窗口。R=B/R=L 均不能清未知批次。 |
|
||
| 普通冲突误判损坏 | 最新 baseline 可是远端冲突观察值,而 pending.BaseValue 仍是编辑时基线;二者不要求始终相等。独立用例覆盖这个合法状态重开及重复冲突,不建议加入错误的无条件相等校验。 |
|
||
| remoteStore=false | 只形成 localOnly;不取消既有远端 pending,不被旧批次确认覆盖。显式远端 Update 或 Delete 同次提交清除对应覆盖。 |
|
||
| 锁/Dispose 竞态 | 状态操作和保存受同一同步 gate 保护,Dispose 也使用该 gate,重复 Dispose 不释放新实例的锁。3B 必须在释放此同步状态前排空已准入网络工作;本层不冒充已实现该异步生命周期。 |
|
||
|
||
## 5. 独立执行证据
|
||
|
||
独立宿主:`CodexOutput/upserver/KVSyncReviewTests/KVSyncReviewTests.csproj`。它直接编译上面三个生产 `.cs` 文件,引用项目现有 Newtonsoft,未用复制/镜像状态机代替实现,也没有 HTTP 代码或 Unity 自动化。
|
||
|
||
最终执行:**13 组场景、127 个断言全部通过**。组数与断言数不同,不能描述成 127 个独立完整业务场景。
|
||
|
||
证据目录:`CodexOutput/upserver/KVSyncReviewTests/Evidence/20260922-072831-309/`,汇总 `Latest-review.log` 含断言与源码 hash;入口控制台结果为 `KVSyncReviewTests/Latest-console.log`。首次执行证据另存于 `Evidence/20260922-072648-825/`,未覆盖。
|
||
|
||
覆盖重点:
|
||
|
||
- 完整绝对路径对照及 Windows 两类非法根路径拒绝。
|
||
- active v1 + pending v2 重启,R=B/R=L 不解锁,v1 确认推进 v2 base。
|
||
- localOnly 叠加、确认不覆盖及 Delete 清覆盖。
|
||
- 五个磁盘故障点:BeforeWrite、AfterWrite、AfterFlush、BeforeReplace、AfterReplace;内存不发布、冻结、实际磁盘重开与不确定标记。
|
||
- 数字溢出、字段类型、重复字段和尾随根拒绝;每次拒绝后修复测试材料并重新打开,验证句柄未泄漏。
|
||
- 12 种批次关联损坏(包含双 active/unknown、无对应 pending、目标/base 不符、非法批次 ID/结构等),以及合法同序号/更新序号的对照。
|
||
- 普通冲突 B 与最新远端观察不同的合法快照重开。
|
||
- 有效主档/损坏备份、缺失主档/遗留备份、独占锁和重复 Dispose。
|
||
|
||
上述磁盘数据均为合成测试字符串,根目录均在审查目录,没有读取或写入真实游戏缓存。URI 只作为身份字符串使用,没有网络请求。
|
||
|
||
## 6. 主会话证据的只读复核
|
||
|
||
- 已阅读 `KVSyncTests/Program.cs` 和 `KVSyncTests/Latest.log`:**86 通过、0 失败**。其中另含真实子进程独占锁、写步骤进程退出、101 个 key 分批、24 个并发编辑、超限文件以及更多输入/恢复用例。本 agent 没有重跑或改动主测试。
|
||
- 已读取 `kv3a-unity-compile.json`:`Success=true`,`ErrorCount=0`,`WarningCount=274`。本 agent 没有启动或控制 Unity;这是主会话执行并落盘的编译证据。
|
||
|
||
## 7. 后续门与限制
|
||
|
||
1. 3B 验证真实 PlayerKVClient 配可控传输、固定会话、票据精确确认/Superseded、水位、取消和 Close 原子准入;不能用本次同步 gate 用例替代异步关闭验收。
|
||
2. 3C 再做组合和限定联调;本次没有进行正式服 KV 写入或 Unity 业务存档运行验收。
|
||
3. Windows/.NET 文件故障和进程退出测试不证明移动设备文件替换、文件锁错误分类及断电耐久性。当前 Unity 编译成功也不等于最终平台文件系统验收;真机/最终包按既定计划单列,当前不打包。
|
||
4. Json.NET 扩展语法继续按阶段 2/方案约定兼容;结构校验不是防篡改签名,也不能识别所有仍满足格式的外部内容改写。本轮不新增手写 JSON 解析器或密码学完整性机制。
|
||
5. 本地 Ordinal 字典不保证服务端数据库 collation 区分大小写;服务器仍无 CAS。不得扩展为跨设备强一致保证,实际生产 key 和桥接安全门留阶段 4。
|
||
|
||
**收尾结论:R1 闭环,3A 限定代码审查通过;下一步是已批准范围内的 3B 开发与独立验收。**
|