Files
ft/CodexOutput/upserver/阶段3方案评审-ZCode-2026-09-22.md

92 lines
9.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 阶段3技术方案独立评审(ZCode 会话)
日期:2026-09-22。评审人:ZCode 主会话(应用户"对阶段3技术方案做一下评审"要求执行)。评审对象:《阶段3缓存同步方案与评审-2026-09-22.md》全文、既有独立方案审查闭环,以及方案所述边界与当前工作区实际状态的一致性。本轮只读核查与落盘本文件,未修改任何生产代码、状态文档或测试。
## 裁决摘要
**技术方案内容:通过(含对 R1–R4 闭环的复核)。两条收紧策略:建议用户确认(附条件,见第四节)。但存在一项 P0 级存证失真和一项 P1 级验收门未闭合,必须在推进 3B 前纠正。**
方案本身的工程质量高:写前日志、单写者租约、原子替换、快照严格校验、B/L/R 三方比较、未知保守冻结等合同完整自洽,且已写出的 3A 代码与方案逐项吻合。问题不在设计,在于**文档记录的工作状态与工作区实际状态已经分叉**。
## 一、P0:存证与实际状态失真(阻塞 3B 放行)
时间线(文件 mtime 取证):
| 时间 | 事件 | 证据 |
|---|---|---|
| 15:01 | 接手入口/开发状态/TODO 落盘,均写明"本轮仅文档、无生产代码修改或测试执行、待用户确认后进入3A" | 三文件 mtime 2026-09-22 15:01:41 |
| 15:03 | 独立方案审查终验完成,记录主方案 hash `097EE094…`,明确"用户确认与3A实施仍未勾选" | 阶段3缓存同步独立方案审查-2026-09-22.md |
| 15:14 | 主方案被再次修改:顶部改为"用户本轮'继续'已确认新策略,现进入3A实施",检查表勾选用户确认 | 当前 hash `70c7C5D8…` ≠ 审查终验 hash |
| 15:19–15:25 | 3A 三个生产文件写入(PlayerKVSyncState/PlayerKVCacheStore/PlayerKVSyncModels) | 文件 mtime |
| 15:24 / 15:27 | KVSyncTests 执行:74 项、86 项全部通过 | Initial.log / Latest.log |
三个具体问题:
1. **"用户确认"依据不足且自相矛盾。** 主方案顶部称用户以"继续"确认两条收紧策略,但同文档底部结论仍写"待用户确认两项策略,生产代码尚未实现";独立审查明确要求"这两条不能由独立技术审查替代用户确认,也不能由历史G1推定"。本轮用户实际动作是要求评审方案,不构成对该两策略的确认。修改发生在独立审查终验 hash 之后,未经复核。
2. **状态文档与实际相反。** 15:01 的三份状态文档声明无生产代码与未执行测试;实际 3A 已实现且 86 项测试已通过。任何后续接手者按文档理解会被误导,违反项目自身落盘协议。
3. **3A 实施事实缺正式记载。** 86 项测试通过没有对应验收文档,未记载与方案 G3A 用例矩阵的覆盖对应关系。
**整改要求(进入 3B 前):** ① 用户对本报告第四节明确表态;② 主方案顶部/底部及三份状态文档按实际状态改写一致,"用户确认"以用户的明确表述为准;③ 3A 已实施事实按实际补记载(文件清单、测试证据、未完成项单列)。
## 二、P1:G3A 验收门未闭合
按方案自设验收门,3A 完成需要"状态转换、磁盘故障、隔离及重启恢复测试,**Unity 兼容编译**"与独立 review。当前:
- 离线测试 86 项通过(合成 fixture,含磁盘边界故障注入、租约跨进程、损坏快照拒绝、序号溢出等);
- **Unity 编译验证缺失**(现有 kv-unity-compile.json 为阶段2证据,不含三个新文件);
- **3A 代码独立复审缺失**(本报告评审了方案与代码一致性,不替代按 G3A 清单的逐项验收);
- **G3A 验收报告未落盘**。
## 三、技术评审结论
### 3.1 通过项(方案与已写代码逐项核对)
| 领域 | 核对结果 |
|---|---|
| 写前日志 | BeginBatch 先 Commit 落盘再暴露批次(`batch = snapshot.Active` 在 Commit 成功后),符合§7.1 |
| 批次规则 | sequence 升序、连续同类型、≤10 key:`TakeWhile(Exists==首项).Take(10)`;解码校验同规则 |
| v1/v2 并发 | ConfirmBatch 精确 sequence 移除、v2 基线推进 `WithBase(v1)`;与§7.1 一致 |
| B/L/R | R==L 确认移除、R==B 保留、均不等→Conflict;unknown 优先且不因观察解除;整次合并单次落盘 |
| 磁盘顺序 | tmp→Flush(true)→File.Replace(保留bak)/首次Move;mayHaveCommitted 窗口覆盖 AfterReplace 故障注入 |
| 快照校验 | 身份绑定(api/playerId 必须匹配)、sequence 唯一且<NextSequence、批次-pending 关联(含被替换旧 sequence 的合法引用)、≤10/同类型/升序、64MB 上限、未来版本拒绝 |
| 遗留证据 | 主档缺失但有 bak/tmp → RecoveryRequired;主档有效时 bak 损坏仅忽略;不静默建空档(Get 失败不 Ready) |
| 会话隔离 | 构造时清 AuthenticationInvalid 但保留 Unknown;Active 遗留转 Unknown;与§5"重登不能只改枚举恢复"一致 |
| 取消语义 | R2 已在状态层落实(等待者取消不影响事实,由 3B 包装 WaitForTicketAsync) |
| 对现有代码断言 | PlayFabMgr 缓冲桶+每桶10key+40s 周期、失败仅日志;UserService 私有 apiSession/LoginLifetime;CustomServerMgr SessionVersion;S101AccountSession 每次 Login 新 CookieContainer——全部属实 |
### 3.2 保留意见(不阻塞,需在 3B/3C 或措辞中处理)
1. **P2|4xx 永久冻结的运营代价。** 非 200 一律 MayHaveCommitted=true,叠加政策1(无自动解锁),单次服务端 400(如 key/值超限被拒)将永久冻结该账号命名空间,且本批不含人工恢复工具。建议:(a) 只读核查 N3-Server-CN 源码,若可证明 400/413 为"先校验后写",以差异裁决将其降级为确定未提交;(b) 将"诊断导出+人工解锁流程"列为 3C 交付或紧随其后的必做项。
2. **P3|Unix/Android 跨进程租约失效。** FileShare.None 在 .NET/Unix 不跨进程强制;Windows 双进程 Busy 测试通过,同进程互斥(主要风险:同进程换号未关旧 owner)仍有效。需在最终包平台差异清单明示。
3. **P3|UnknownOutcome 分支 baseline 被观察值覆盖。** Reconcile 在 unknown 分支将 baseline 更新为本次远端观察 R。写入已冻结故当前无实害,但 baseline 语义由"最后确认远端"漂移为"最后一次观察",未来若引入解锁机制会误导 B/L/R。建议统一:unknown 分支保留原 baseline,观察仅入 conflictObservations。
4. **P3|3B 次序合同。** 批次在途时 RecordReadFailure/Reconcile 被 Active!=null 阻塞(状态机有意为之);3B 协调器必须先提交成功批次的 ConfirmBatch、后记录 401 失效,否则成功写会被冻结为 unknown(保守但损失可用性)。应写入 3B 合同测试。
5. **P3|ReadLocal 每次全量拷贝。** 51+ key O(n) 拷贝对高频玩法读有成本,阶段4接入时如需可加只读缓存视图。
## 四、两条收紧策略裁决建议(待用户确认)
1. **未知写不自动解锁(即使 Get 观察等于基线/目标)。建议确认。** 服务端无 revision/CAS/幂等查询,任何"看起来没写"都不能排除迟到提交;自动重发的最坏后果是资产重复扣减。代价(可能永久冻结)应由后续服务端终态接口或恢复工具解决,不应由客户端猜测。附带条件见 3.2-1。
2. **主缓存损坏时备份不自动作为可写恢复源。建议确认。** 备份可能缺最后一次已接受修改,自动续写等于静默丢数据;RecoveryRequired+保留证据+人工恢复是正确取向。附带条件:人工恢复流程文档应尽早补齐,不能长期只冻结无出路。
## 五、建议放行顺序
1. 用户对第四节两条策略明确表态(确认或修改)。
2. 按第一节整改要求修正全部状态文档与主方案的自相矛盾。
3. 补 G3A 门:Unity 含三新文件的编译验证、3A 代码独立复审、G3A 验收报告。
4. 之后按方案进入 3B(固定会话及同步器),3B/3C 仍按小阶段验收推进。
## 证据清单
- 主方案当前 SHA256:`70C7C5D8D826964CE46159E295A150B74113431CAF33CB967CF28A5E624FF75F`(独立审查终验记录为 `097EE094…`,证明终验后又被修改)。
- KVSyncTests:Initial.log 74 通过 / Latest.log 86 通过,0 失败,仅合成 fixture。
- 已读核对的代码:Services/PlayerData 全部 5 文件;PlayFabMgr 缓冲实现;UserService/CustomServerMgr 会话标识;S101AccountSession Cookie 处理。
- 本轮未执行:Unity 编译、正式服访问、生产代码修改。
---
## 更正注记(2026-09-22,用户裁决后由主会话补充)
1. **第二节 P1“G3A 验收门未闭合”已过时**:Unity 编译(kv3a-unity-compile.json,0 错误/274 警告)、《阶段3A独立代码审查-2026-09-22.md》(最终限定通过)与《阶段3A缓存状态与磁盘验收-2026-09-22.md》均在本报告评审时点前后落盘,G3A 门已闭合。该发现反映评审时点,不代表当前状态。
2. **第三节 3.2-3 为误报,撤回**:复核 PlayerKVSyncState.Reconcile,unknown 分支在 baseline 更新语句之前 return,原 baseline 保留、观察仅入 conflictObservations,与方案 §6 一致,实现正确。
3. **第一节 D2 相关判断部分过时**:本报告依据 15:28 前的文件快照判断“三份入口文档未同步、开发日志与事实不符”;实际同步于 15:32/15:38 完成,系并发观察时序差,开发日志原记录准确。3B 亦已于其后开工(分工实施,实施记录另列)。
4. **“用户确认依据不足”已解决**:用户 2026-09-22 正式追认两条收紧策略,定性“用户后续确认”(见接手入口顶部裁决);相关状态文档已按事实修正。