# 阶段2独立 KV 适配验收 日期:2026-09-22。客户端 C:/projects/ft/Client;正式 API **http://s101.local:18080/**。 ## 结论与开发边界 阶段2独立协议适配及本批验收通过:生产 Get/Set/Delete 客户端已实现,42 项契约测试、16 项真实服务联调检查和 Unity 编译通过。已完成独立代码审查;JSON 语法兼容性按下文裁决保留,不把它写成标准 JSON 严格校验。 **尚未把游戏存档切到 KV。** PlayFab 存档入口和 SDK 仍保留;没有新增生产会话桥接、缓存同步、迁移或俱乐部功能。本批没有打包、提交或发布。最小登录已有证据继续有效,平台/UI 网络、主动推送、人工玩法/完整存档及最终渠道包仍待验收。 实施依据:[阶段2启动裁决](阶段确认与阶段2启动裁决-2026-09-22.md);独立报告:[阶段2独立KV代码审查](阶段2独立KV代码审查-2026-09-22.md)。每步记录在[开发日志](开发日志.md)。 ## 本批改动 - 新增 `Client/Assets/Scripts/Services/PlayerData/PlayerKVModels.cs`、`PlayerKVClient.cs` 及 Unity meta。 - 注入调用方拥有的固定会话 HttpClient;复制请求参数,不修改共享请求头/基址,不释放注入客户端,不自动重登或重试。 - Get 返回只读字符串字典;失败 Data=null,明确区分合法空字典。Set/Delete 接受 HTTP 200 空响应。401/403、HTTP、网络、超时、取消、参数和协议错误分别标识。 - 写请求进入传输后失败,保守返回 MayHaveCommitted=true;调用方不能将失败理解为一定未写入,更不能据此盲目重试。 - 新增独立联调宿主 `KVLiveTests`,完善 `KVContractTests`;不修改现有游戏登录、存档和 SignalR 入口。 ## 验收证据 | 项目 | 结果与证据 | 证明范围 | |---|---|---| | 生产源码契约测试 | [42项通过](KVContractTests/Latest.log) | .NET 9 宿主、项目 Newtonsoft、实际两个生产文件;请求/响应、快照、错误、取消、所有权 | | 联调宿主构建 | [0错误/0警告](KVLiveTests/build.log) | 直接编译生产 KV 和 S101AccountSession 源码 | | 正式服联调 | [16项通过](KVLiveTests/Latest.log)、[结果](KVLiveTests/Latest-result.json) | 真实 s101 网络、独立 Cookie、101/102 专用 key,非 Unity UI/真机 | | 清理 | [精确manifest](KVLiveTests/codex_kv_s2_20260922_3bc01858f94e4f67b984aeaae018236d.manifest.json) | 两账号全部测试 key 删除后读回为空;HadUnknownWrite=false | | Unity 编译 | [Success=true,0错误/274警告](kv-unity-compile.json) | C盘 Unity 2022.3.62f2c1 兼容编译;已有警告未清零 | | 工具身份 | [CLI Loop 2.2.0及C盘DataPath](kv-unity-version.json) | 不操作D盘,不使用UnitySkills,不提高动态权限 | 正式联调验证:无 Cookie 的 Get/空 Set/空 Delete 拒绝;两账号 key 碰撞预检;新增、字符串/空字符串/JSON字符串原样读回、不存在 key 省略;同名 key 账号隔离;单 key 覆盖;null/空 keys 全读;空操作与删除不存在 key;每账号重新登录并新建 Cookie/HttpClient 后读回;删除101不影响102;最终清理及业务 KV 前后内存比较相同。 只写删 `codex_kv_s2_20260922_3bc01858f94e4f67b984aeaae018236d_` 下四个预先列明 key。不存在 key 未实际写入。没有写删既有业务 key,不落盘 Cookie 或真实存档值。重登读回证明服务端跨客户端会话保留,不冒充数据库重启或灾备恢复测试。 Editor 在导入前已 Stop Play,本批没有重新启动游戏。独立网络测试不创建 Hub,也不替代 Unity 游戏内 KV 验收。清理已成功,无需再次执行写删。 ## 独立评审后的明确裁决 1. **JSON语法兼容性:接受并记录。** 项目 Json.NET 允许未加引号字段、尾逗号等扩展语法,本批不添加新的解析库或手写语法分析器。“严格”只指完整单根对象、data 对象及字符串值、拒绝重复字段与尾随内容。扩展语法仍可能得到成功空 data;不是标准 JSON 全语法验证。该边界不改变有效服务器契约;阶段4必须重审空档初始化策略,禁止只凭空字典自动覆盖原档。 2. **固定身份依赖调用方契约。** readonly HttpClient 不会自动锁定可变 CookieContainer;调用方必须每账号/环境独立 transport、禁用重定向、退出取消并等待结束后释放。测试宿主已按此实现,生产桥接仍待阶段3/4完整评审。 3. **不声明服务端 key 大小写隔离。** 客户端 Ordinal 字典不能证明 MySQL 排序规则;服务器契约未保证 A/a 是两个 key。本批测试未依赖这种行为。 4. **不声明可靠同步已完成。** 服务端无 revision/CAS,结果未知、离线脏数据、重试顺序与冲突策略属于下一阶段。 ## 当前阶段与下一步 | 阶段 | 状态 | |---|---| | 1 映射/契约方案 | 已评审,本批复核 | | 最小登录专项 | 核心实现与主要自动验收通过;平台/人工/最终包待验收单列 | | 2 独立KV适配 | 本批实现、契约/联调/清理/Unity编译和限定review完成 | | 3 缓存与可靠同步 | 下一步先完整评审方案,尚未编码 | | 4 游戏存档切换 | 未开始,必须先完成3及迁移/空档保护评审 | | 5 外围业务 | SignalR基础已提前完成,其余暂停 | | 6 SDK删除与最终包 | 最后执行 | 阶段3评审需明确:固定生产会话桥接、账号/环境缓存命名空间、读取失败禁止建空档、dirty版本与单通道写入、写结果未知后的核对策略、401/退出/换号取消边界及竞态验收。先落盘方案和评审裁决,再编码;不以本次通过自动放行游戏数据迁移或 SDK 删除。